KSENSOR_OPS(9E) Driver Entry Points KSENSOR_OPS(9E)

NAME


ksensor_ops, kso_kind, kso_scalar - ksensor entry points

SYNOPSIS


#include <sys/sensors.h>

int
kso_kind(void *driver, sensor_ioctl_kind_t *kind);

int
kso_scalar(void *driver, sensor_ioctl_scalar_t *scalar);

INTERFACE LEVEL


Volatile - This interface is still evolving in illumos. API and ABI
stability is not guaranteed.

PARAMETERS


driver A pointer to the driver's private data that was passed as
an argument to ksensor_create(9F).

kind A pointer to a structure the driver will fill out to
answer what kind of sensor it is.

scalar A pointer to a structure that the driver will fill out to
answer the current value of the sensor.

DESCRIPTION


The ksensor(9E) framework requires that device drivers provide an
operations vector when registering a sensor with ksensor_create(9F).
The operations vector uses the ksensor_ops_t structure and is
implemented in terms of two entry points kso_kind() and kso_scalar(),
both of which are required.

In all entry points, the driver will be passed back driver, which is
the argument registered when the sensor was created. This provides the
driver a direct means to determine which sensor the framework is asking
about and allows the same operations vector to serve multiple instances
of a sensor.

The ksensor framework does not serialize calls to the operations
vectors as part of its contract to sensor providers. Drivers must
assume that the various entry points will be called in parallel from
multiple threads and that if any locking is required, it is the
driver's responsibility.

ksensor kind
The kso_kind() entry point is used to answer the question of what kind
of sensor something is. A ksensor's kind indicates to the user what
type of physical phenomenon the sensor manages such as temperature,
voltage, etc. Some sensors are synthesized from physical phenomena,
but don't represent one themselves. These sensors use the kso_kind()
entry point to indicate that and what they're derived from. For many
drivers, they can use one of the stock implementations that the kernel
provides such as ksensor_kind_temperature(9F),
ksensor_kind_voltage(9F), or ksensor_kind_current(9F) if they're a
stock temperature, voltage, or current sensor.

For drivers that must implement this themselves, they should fill out
the members of the sensor_ioctl_kind_t structure as follows:

sik_kind This member should be filled in with the kind of the
sensor from the list in ksensor(9E). The driver should
not use SENSOR_KIND_UNKNOWN. If the driver uses
SENSOR_KIND_SYNTHETIC then it should fill in sik_derive.

sik_derive If the driver did not set sik_kind to
SENSOR_KIND_SYNTHETIC, then this member should not be set
and left at its default value that the framework
provides. Otherwise, if the type that it is derived from
is known, then it should be set to one of the kind values
other than SENSOR_KIND_UNKNOWN and SENSOR_KIND_SYNTHETIC.

ksensor scalar
The kso_scalar() entry point is used to return information about a
scalar value read from a sensor. This is the primary interface by
which a value is read from a device. For more information on scalar
sensors and the intended semantics, see the Sensor Types, Kinds, Units,
and Naming section of ksensor(9E).

When this entry point is called, the driver should fill out the members
of the sensor_ioctl_scalar_t structure as follows:

sis_unit A uint32_t that indicates the unit that the sensor is in.
This should be one of the units from the list in
ksensor(9E) and should not be SENSOR_UNIT_UNKNOWN.
SENSOR_UNIT_NONE should only be used if the sensor's kind
is SENSOR_KIND_SYNTHETIC.

sis_gran An int32_t that indicates the granularity or resolution
of the sensor. The granularity indicates the number of
increments per unit in the measurement. A value such as
10 indicates that the value is in 10ths of the unit. If
this was a temperature sensor, one would need to divide
sit_value by 10 to obtain degrees. On the other hand a
negative granularity indicates one would need to multiply
sit_value to get the actual base unit. For example, a
value of -2 would indicate that actual number of degrees,
you'd need to multiply the value by two.

sis_prec A uint32_t that represents the accuracy of the sensor
itself and is measured in units of the granularity. For
example, a temperature sensor that has a granularity of
1, meaning the value read from the sensor is in degrees,
and is accurate to +/-5 degrees would set the precision
to 5. Conversely, a temperature sensor that measured in
0.5 degree increments has a granularity of 2. If the
sensor was accurate to +/-1 degree, then it'd have a
precision of 2. If the precision is unknown, it should
be left at zero.

sis_value A int64_t that represents the value read from the sensor.
It is in units of the granularity and is a signed
quantity.

CONTEXT


The kso_kind() and kso_scalar() functions are generally called from
kernel context. While these functions may be called from user context,
the driver must not assume that and should not be copying any data into
or out of a user process.

RETURN VALUES


Upon successful completion, the device driver should have filled out
the corresponding structure into kind or scalar and return 0.
Otherwise, a positive error number should be returned to indicate the
failure.

EXAMPLES


Example 1 Example PCI-based Implementation

The following example shows what this might look like for PCI-based
device driver that has a temperature sensor in configure space. This
example assumes the sensor measures in 0.5 degree increments and is
accurate to +/-1 degree .

#include <sys/ddi.h>
#include <sys/sunddi.h>
#include <sys/sensors.h>

/*
* Our temperature sensor in configuration space. It returns an unsigned
* 32-bit value in 0.5 degree increments that indicates the current
* temperature in degrees C.
*/
#define EX_SENSOR 0x200

/*
* Our granularity is 0.5 degrees. Our precision is +/-1 degree, which
* is 2 units of our granularity, hence we define it as 2.
*/
#define EX_SENSOR_GRAN 2
#define EX_SENSOR_PREC 2

/*
* Driver structure that is registered with ksensor_create(9F). The
* ex_cfg member comes from a call to pci_config_setup() during
* attach(9E).
*/
typedef struct ex {
...
ddi_acc_handle_t ex_cfg;
...
} ex_t;

static int
ex_sensor_temp_read(void *arg, sensor_ioctl_scalar_t *scalar)
{
uint32_t reg;
ex_t *ex = arg;

reg = pci_config_get32(ex->ex_cfg, EX_SENSOR);
scalar->sis_unit = SENSOR_UNIT_CELSIUS;
scalar->sis_gran = EX_SENSOR_GRAN;
scalar->sis_prec = EX_SENSOR_PREC;
scalar->sis_value = reg;
return (0);
}

static const ksensor_ops_t ex_sensor_temp_ops = {
.kso_kind = ksensor_kind_temperature,
.kso_scalar = ex_sensor_temp_read
};

ERRORS


The device driver may return one of the following errors, but is not
limited to this set if there is a more accurate error based on the
situation.

EIO This error should be used when the driver fails to
communicate with the device to read the current
sensor value.

SEE ALSO


ksensor(9E), ksensor_create(9F), ksensor_kind(9F)

illumos May 10, 2024 illumos

tribblix@gmail.com :: GitHub :: Privacy