#include <sys/ddi.h>
#include <sys/sunddi.h>
#include <sys/modctl.h>
#include <sys/conf.h>
#include <sys/devops.h>
#include <sys/zone.h>
#include <sys/sensors.h>
typedef struct ksensor_test {
dev_info_t *kt_dip;
id_t kt_sensor1;
id_t kt_sensor2;
id_t kt_sensor3;
id_t kt_sensor4;
id_t kt_sensor5;
id_t kt_volt;
id_t kt_current;
} ksensor_test_t;
static int
ksensor_test_temp(void *arg, sensor_ioctl_scalar_t *scalar)
{
scalar->sis_unit = SENSOR_UNIT_CELSIUS;
scalar->sis_gran = 4;
scalar->sis_prec = -2;
scalar->sis_value = 23;
return (0);
}
static const ksensor_ops_t ksensor_test_temp_ops = {
.kso_kind = ksensor_kind_temperature,
.kso_scalar = ksensor_test_temp
};
static int
ksensor_test_volt(void *arg, sensor_ioctl_scalar_t *scalar)
{
scalar->sis_unit = SENSOR_UNIT_VOLTS;
scalar->sis_gran = 1000;
scalar->sis_prec = 0;
scalar->sis_value = 3300;
return (0);
}
static const ksensor_ops_t ksensor_test_volt_ops = {
.kso_kind = ksensor_kind_voltage,
.kso_scalar = ksensor_test_volt
};
static int
ksensor_test_current(void *arg, sensor_ioctl_scalar_t *scalar)
{
scalar->sis_unit = SENSOR_UNIT_AMPS;
scalar->sis_gran = 10;
scalar->sis_prec = 0;
scalar->sis_value = 5;
return (0);
}
static const ksensor_ops_t ksensor_test_current_ops = {
.kso_kind = ksensor_kind_current,
.kso_scalar = ksensor_test_current
};
static int
ksensor_test_kind_eio(void *arg, sensor_ioctl_kind_t *kindp)
{
return (EIO);
}
static int
ksensor_test_temp_eio(void *arg, sensor_ioctl_scalar_t *scalar)
{
return (EIO);
}
static const ksensor_ops_t ksensor_test_eio_ops = {
.kso_kind = ksensor_test_kind_eio,
.kso_scalar = ksensor_test_temp_eio
};
static int
ksensor_test_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
{
int ret;
char buf[128];
ksensor_test_t *kt;
switch (cmd) {
case DDI_RESUME:
return (DDI_SUCCESS);
case DDI_ATTACH:
break;
default:
return (DDI_FAILURE);
}
kt = kmem_zalloc(sizeof (ksensor_test_t), KM_SLEEP);
kt->kt_dip = dip;
(void) snprintf(buf, sizeof (buf), "test.temp.%d.1",
ddi_get_instance(dip));
if ((ret = ksensor_create(dip, &ksensor_test_temp_ops, NULL, buf,
"ddi_sensor:test", &kt->kt_sensor1)) != 0) {
dev_err(dip, CE_WARN, "failed to attatch sensor %s: %d", buf,
ret);
goto err;
}
(void) snprintf(buf, sizeof (buf), "test.temp.%d.2",
ddi_get_instance(dip));
if ((ret = ksensor_create(dip, &ksensor_test_temp_ops, NULL, buf,
"ddi_sensor:test", &kt->kt_sensor2)) != 0) {
dev_err(dip, CE_WARN, "failed to attatch sensor %s: %d", buf,
ret);
goto err;
}
(void) snprintf(buf, sizeof (buf), "test.temp.%d.3",
ddi_get_instance(dip));
if ((ret = ksensor_create(dip, &ksensor_test_temp_ops, NULL, buf,
"ddi_sensor:test", &kt->kt_sensor3)) != 0) {
dev_err(dip, CE_WARN, "failed to attach sensor %s: %d", buf,
ret);
goto err;
}
(void) snprintf(buf, sizeof (buf), "test.temp.%d.4",
ddi_get_instance(dip));
if ((ret = ksensor_create(dip, &ksensor_test_temp_ops, NULL, buf,
"ddi_sensor:test", &kt->kt_sensor4)) != 0) {
dev_err(dip, CE_WARN, "failed to attach sensor %s: %d", buf,
ret);
goto err;
}
(void) snprintf(buf, sizeof (buf), "test.eio.%d",
ddi_get_instance(dip));
if ((ret = ksensor_create(dip, &ksensor_test_eio_ops, NULL, buf,
"ddi_sensor:test", &kt->kt_sensor5)) != 0) {
dev_err(dip, CE_WARN, "failed to attach sensor %s: %d", buf,
ret);
goto err;
}
(void) snprintf(buf, sizeof (buf), "test.volt.%d.1",
ddi_get_instance(dip));
if ((ret = ksensor_create(dip, &ksensor_test_volt_ops, NULL, buf,
"ddi_sensor:test", &kt->kt_volt)) != 0) {
dev_err(dip, CE_WARN, "failed to attach sensor %s: %d", buf,
ret);
goto err;
}
(void) snprintf(buf, sizeof (buf), "test.current.%d.1",
ddi_get_instance(dip));
if ((ret = ksensor_create(dip, &ksensor_test_current_ops, NULL, buf,
"ddi_sensor:test", &kt->kt_current)) != 0) {
dev_err(dip, CE_WARN, "failed to attach sensor %s: %d", buf,
ret);
goto err;
}
ddi_set_driver_private(dip, kt);
return (DDI_SUCCESS);
err:
(void) ksensor_remove(dip, KSENSOR_ALL_IDS);
kmem_free(kt, sizeof (ksensor_test_t));
return (DDI_FAILURE);
}
static int
ksensor_test_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
{
ksensor_test_t *kt;
switch (cmd) {
case DDI_DETACH:
break;
case DDI_SUSPEND:
return (DDI_SUCCESS);
default:
return (DDI_FAILURE);
}
kt = ddi_get_driver_private(dip);
if (kt == NULL) {
dev_err(dip, CE_WARN, "failed to find ksensor_test_t");
return (DDI_FAILURE);
}
if (kt->kt_sensor3 != 0 &&
ksensor_remove(dip, kt->kt_sensor3) != 0) {
dev_err(dip, CE_WARN, "failed to remove sensor 3");
return (DDI_FAILURE);
}
kt->kt_sensor3 = 0;
if (ksensor_remove(dip, KSENSOR_ALL_IDS) != 0) {
dev_err(dip, CE_WARN, "failed to remove sensors");
return (DDI_FAILURE);
}
kmem_free(kt, sizeof (*kt));
ddi_set_driver_private(dip, NULL);
return (DDI_SUCCESS);
}
static struct dev_ops ksensor_test_dev_ops = {
.devo_rev = DEVO_REV,
.devo_refcnt = 0,
.devo_getinfo = nodev,
.devo_identify = nulldev,
.devo_probe = nulldev,
.devo_attach = ksensor_test_attach,
.devo_detach = ksensor_test_detach,
.devo_reset = nodev,
.devo_power = ddi_power,
.devo_quiesce = ddi_quiesce_not_needed,
};
static struct modldrv ksensor_test_modldrv = {
.drv_modops = &mod_driverops,
.drv_linkinfo = "Kernel Sensor test driver",
.drv_dev_ops = &ksensor_test_dev_ops
};
static struct modlinkage ksensor_test_modlinkage = {
.ml_rev = MODREV_1,
.ml_linkage = { &ksensor_test_modldrv, NULL }
};
int
_init(void)
{
return (mod_install(&ksensor_test_modlinkage));
}
int
_info(struct modinfo *modinfop)
{
return (mod_info(&ksensor_test_modlinkage, modinfop));
}
int
_fini(void)
{
return (mod_remove(&ksensor_test_modlinkage));
}