#include <mlxcx.h>
#include <sys/sensors.h>
#define MLXCX_TEMP_GRAN 8
static int
mlxcx_temperature_read(void *arg, sensor_ioctl_scalar_t *scalar)
{
boolean_t ok;
uint16_t tmp;
mlxcx_register_data_t data;
mlxcx_temp_sensor_t *sensor = arg;
mlxcx_t *mlxp = sensor->mlts_mlx;
bzero(&data, sizeof (data));
data.mlrd_mtmp.mlrd_mtmp_sensor_index = to_be16(sensor->mlts_index);
ok = mlxcx_cmd_access_register(mlxp, MLXCX_CMD_ACCESS_REGISTER_READ,
MLXCX_REG_MTMP, &data);
if (!ok) {
return (EIO);
}
tmp = from_be16(data.mlrd_mtmp.mlrd_mtmp_temperature);
sensor->mlts_value = (int16_t)tmp;
tmp = from_be16(data.mlrd_mtmp.mlrd_mtmp_max_temperature);
sensor->mlts_max_value = (int16_t)tmp;
bcopy(data.mlrd_mtmp.mlrd_mtmp_name, sensor->mlts_name,
sizeof (sensor->mlts_name));
scalar->sis_unit = SENSOR_UNIT_CELSIUS;
scalar->sis_gran = MLXCX_TEMP_GRAN;
scalar->sis_prec = 0;
scalar->sis_value = (int64_t)sensor->mlts_value;
return (0);
}
static const ksensor_ops_t mlxcx_temp_ops = {
.kso_kind = ksensor_kind_temperature,
.kso_scalar = mlxcx_temperature_read
};
void
mlxcx_teardown_sensors(mlxcx_t *mlxp)
{
if (mlxp->mlx_temp_nsensors == 0)
return;
(void) ksensor_remove(mlxp->mlx_dip, KSENSOR_ALL_IDS);
kmem_free(mlxp->mlx_temp_sensors, sizeof (mlxcx_temp_sensor_t) *
mlxp->mlx_temp_nsensors);
}
boolean_t
mlxcx_setup_sensors(mlxcx_t *mlxp)
{
mlxcx_register_data_t data;
boolean_t ok;
mlxp->mlx_temp_nsensors = 0;
bzero(&data, sizeof (data));
ok = mlxcx_cmd_access_register(mlxp, MLXCX_CMD_ACCESS_REGISTER_READ,
MLXCX_REG_MTCAP, &data);
if (!ok) {
return (B_FALSE);
}
if (data.mlrd_mtcap.mlrd_mtcap_sensor_count == 0) {
return (B_TRUE);
}
mlxp->mlx_temp_nsensors = data.mlrd_mtcap.mlrd_mtcap_sensor_count;
mlxp->mlx_temp_sensors = kmem_zalloc(sizeof (mlxcx_temp_sensor_t) *
mlxp->mlx_temp_nsensors, KM_SLEEP);
for (uint8_t i = 0; i < mlxp->mlx_temp_nsensors; i++) {
char buf[32];
int ret;
if (snprintf(buf, sizeof (buf), "temp%u", i) >= sizeof (buf)) {
mlxcx_warn(mlxp, "sensor name %u would overflow "
"internal buffer");
goto err;
}
mlxp->mlx_temp_sensors[i].mlts_mlx = mlxp;
mlxp->mlx_temp_sensors[i].mlts_index = i;
ret = ksensor_create_scalar_pcidev(mlxp->mlx_dip,
SENSOR_KIND_TEMPERATURE, &mlxcx_temp_ops,
&mlxp->mlx_temp_sensors[i], buf,
&mlxp->mlx_temp_sensors[i].mlts_ksensor);
if (ret != 0) {
mlxcx_warn(mlxp, "failed to create temp sensor %s: %d",
buf, ret);
goto err;
}
}
return (B_TRUE);
err:
mlxcx_teardown_sensors(mlxp);
return (B_FALSE);
}