KSENSOR_OPS(9E) | Driver Entry Points | KSENSOR_OPS(9E) |
ksensor_ops
,
kso_kind
, kso_scalar
— ksensor entry points
#include
<sys/sensors.h>
int
kso_kind
(void *driver,
sensor_ioctl_kind_t *kind);
int
kso_scalar
(void *driver,
sensor_ioctl_scalar_t *scalar);
Volatile - This interface is still evolving in illumos. API and ABI stability is not guaranteed.
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.
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:
SENSOR_KIND_UNKNOWN
. If the driver uses
SENSOR_KIND_SYNTHETIC
then it should fill in
sik_derive.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
.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:
SENSOR_UNIT_UNKNOWN
.
SENSOR_UNIT_NONE
should only be used if the
sensor's kind is SENSOR_KIND_SYNTHETIC
.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.
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.
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 };
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
May 10, 2024 | OmniOS |