acpi_thinkpad: bring back sensors framework
authorAlexander Polakov <polachok@gmail.com>
Wed, 30 Sep 2009 00:20:15 +0000 (00:20 +0000)
committerAlexander Polakov <polachok@gmail.com>
Wed, 14 Oct 2009 13:04:12 +0000 (17:04 +0400)
sys/dev/acpica5/acpi_thinkpad/acpi_thinkpad.c

index 9122e11..db0d4be 100644 (file)
@@ -41,6 +41,7 @@
 #include <sys/param.h>
 #include <sys/kernel.h>
 #include <sys/bus.h>
+#include <sys/sensors.h>
 #include <machine/cpufunc.h>
 #include <machine/clock.h>
 
@@ -129,6 +130,9 @@ ACPI_MODULE_NAME("IBM")
 #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 {
@@ -167,6 +171,10 @@ 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;
 };
@@ -270,9 +278,10 @@ static int acpi_ibm_sysctl_get(struct acpi_ibm_softc *sc, int method);
 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),
@@ -344,6 +353,7 @@ acpi_ibm_attach(device_t dev)
        struct acpi_ibm_softc   *sc;
        devclass_t              ec_devclass;
        struct acpi_softc       *acpi_sc;
+       int i;
 
        ACPI_FUNCTION_TRACE((char *)(uintptr_t) __func__);
 
@@ -405,21 +415,30 @@ acpi_ibm_attach(device_t dev)
                    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)
@@ -432,6 +451,7 @@ acpi_ibm_attach(device_t dev)
 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);
@@ -443,6 +463,12 @@ acpi_ibm_detach(device_t 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);
@@ -891,21 +917,20 @@ acpi_ibm_sysctl_init(struct acpi_ibm_softc *sc, int method)
        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;
                
                /* 
@@ -913,17 +938,31 @@ acpi_ibm_thermal_sysctl(SYSCTL_HANDLER_ARGS)
                 * 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