#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/bus.h>
+#include <sys/sensors.h>
#include <machine/cpufunc.h>
#include <machine/clock.h>
#define IBM_NAME_EVENTS_GET "MHKP"
#define IBM_NAME_EVENTS_AVAILMASK "MHKA"
+#define IBM_NUM_SENSORS 9
+#define IBM_THERMAL_SENSORS 8
+
#define ABS(x) (((x) < 0)? -(x) : (x))
struct acpi_ibm_softc {
int events_mask_supported;
int events_enable;
+ /* sensors(9) related */
+ struct ksensordev sensordev;
+ struct ksensor sensors[IBM_NUM_SENSORS];
+
struct sysctl_ctx_list sysctl_ctx;
struct sysctl_oid *sysctl_tree;
};
static int acpi_ibm_sysctl_set(struct acpi_ibm_softc *sc, int method, int val);
static int acpi_ibm_eventmask_set(struct acpi_ibm_softc *sc, int val);
-static int acpi_ibm_thermal_sysctl(SYSCTL_HANDLER_ARGS);
static void acpi_ibm_notify(ACPI_HANDLE h, UINT32 notify, void *context);
+static void acpi_ibm_refresh(void *);
+
static device_method_t acpi_ibm_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, acpi_ibm_probe),
struct acpi_ibm_softc *sc;
devclass_t ec_devclass;
struct acpi_softc *acpi_sc;
+ int i;
ACPI_FUNCTION_TRACE((char *)(uintptr_t) __func__);
sc, i, acpi_ibm_sysctl, "I",
acpi_ibm_sysctls[i].description);
}
-
- /* Hook up thermal node */
- if (acpi_ibm_sysctl_init(sc, ACPI_IBM_METHOD_THERMAL)) {
- SYSCTL_ADD_PROC(&sc->sysctl_ctx,
- SYSCTL_CHILDREN(sc->sysctl_tree), OID_AUTO,
- "thermal", CTLTYPE_STRING | CTLFLAG_RD,
- sc, 0, acpi_ibm_thermal_sysctl, "I",
- "Thermal zones");
- }
-
ACPI_SERIAL_END(ibm);
/* Handle notifies */
AcpiInstallNotifyHandler(sc->handle, ACPI_DEVICE_NOTIFY,
acpi_ibm_notify, dev);
+
+ /* Attach sensors(9). */
+ if (sensor_task_register(sc, acpi_ibm_refresh, 5)) {
+ device_printf(sc->dev, "unable to register update task\n");
+ return 1;
+ }
+ strlcpy(sc->sensordev.xname, device_get_nameunit(sc->dev),
+ sizeof(sc->sensordev.xname));
+
+ for (i = 0; i < IBM_THERMAL_SENSORS; i++) {
+ sc->sensors[i].type = SENSOR_TEMP;
+ sensor_attach(&sc->sensordev, &sc->sensors[i]);
+ }
+
+ sc->sensors[i].type = SENSOR_FANRPM;
+ sensor_attach(&sc->sensordev, &sc->sensors[i]);
+
+ sensordev_install(&sc->sensordev);
+
#if defined(__FreeBSD__)
/* Hook up light to led(4) */
if (sc->light_set_supported)
static int
acpi_ibm_detach(device_t dev)
{
+ int i;
ACPI_FUNCTION_TRACE((char *)(uintptr_t) __func__);
struct acpi_ibm_softc *sc = device_get_softc(dev);
ACPI_SERIAL_END(ibm);
AcpiRemoveNotifyHandler(sc->handle, ACPI_DEVICE_NOTIFY, acpi_ibm_notify);
+
+ sensordev_deinstall(&sc->sensordev);
+ for (i = 0; i < IBM_THERMAL_SENSORS; i++)
+ sensor_detach(&sc->sensordev, &sc->sensors[i]);
+ sensor_task_unregister(sc);
+
#if defined(__FreeBSD__)
if (sc->led_dev != NULL)
led_destroy(sc->led_dev);
return (FALSE);
}
-static int
-acpi_ibm_thermal_sysctl(SYSCTL_HANDLER_ARGS)
+void
+acpi_ibm_refresh(void *arg)
{
struct acpi_ibm_softc *sc;
- int error = 0;
char temp_cmd[] = "TMP0";
- int temp[8];
+ int i, data, temp[8], speed;
ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
- sc = (struct acpi_ibm_softc *)oidp->oid_arg1;
+ sc = (struct acpi_ibm_softc *)arg;
ACPI_SERIAL_BEGIN(ibm);
- for (int i = 0; i < 8; ++i) {
+ for (i = 0; i < IBM_THERMAL_SENSORS; ++i) {
temp_cmd[3] = '0' + i;
/*
* when the respecting sensor is not available
*/
if (ACPI_FAILURE(acpi_GetInteger(sc->ec_handle, temp_cmd,
- &temp[i])) || ABS(temp[i]) == 128 || temp[i] == 0)
- temp[i] = -1;
- else if (sc->thermal_updt_supported)
+ &temp[i])) || ABS(temp[i]) == 128 || temp[i] == 0) {
+ sc->sensors[i].flags |= SENSOR_FINVALID;
+ data = 0;
+ }
+ else if (sc->thermal_updt_supported) {
/* Temperature is reported in tenth of Kelvin */
- temp[i] = (temp[i] - 2732 + 5) / 10;
+ sc->sensors[i].value = data * 100000;
+ }
+ sc->sensors[i].value = data * 1000000 + 273150000;
}
-
- error = sysctl_handle_opaque(oidp, &temp, 8*sizeof(int), req);
+ sc->sensors[i].flags &= ~SENSOR_FINVALID;
+ if (sc->fan_handle) {
+ if (ACPI_FAILURE(acpi_GetInteger(sc->fan_handle,
+ NULL, &data)))
+ sc->sensors[i].flags |= SENSOR_FINVALID;
+ data = -1;
+ }
+ else {
+ ACPI_EC_READ(sc->ec_dev, IBM_EC_FANSPEED, &speed, 2);
+ data = speed;
+ }
+
+ sc->sensors[i].value = data;
ACPI_SERIAL_END(ibm);
- return (error);
}
static void