Add fan sensor support, from Thomas E. Spanjaard

This commit is contained in:
jmcneill 2008-10-18 16:35:40 +00:00
parent e610f24a9a
commit e38f75f075
1 changed files with 76 additions and 10 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: thinkpad_acpi.c,v 1.15 2008/05/05 00:14:11 jmcneill Exp $ */
/* $NetBSD: thinkpad_acpi.c,v 1.16 2008/10/18 16:35:40 jmcneill Exp $ */
/*-
* Copyright (c) 2007 Jared D. McNeill <jmcneill@invisible.ca>
@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: thinkpad_acpi.c,v 1.15 2008/05/05 00:14:11 jmcneill Exp $");
__KERNEL_RCSID(0, "$NetBSD: thinkpad_acpi.c,v 1.16 2008/10/18 16:35:40 jmcneill Exp $");
#include <sys/types.h>
#include <sys/param.h>
@ -48,7 +48,9 @@ __KERNEL_RCSID(0, "$NetBSD: thinkpad_acpi.c,v 1.15 2008/05/05 00:14:11 jmcneill
#include <machine/pio.h>
#endif
#define THINKPAD_NSENSORS 8
#define THINKPAD_NTEMPSENSORS 8
#define THINKPAD_NFANSENSORS 1
#define THINKPAD_NSENSORS (THINKPAD_NTEMPSENSORS + THINKPAD_NFANSENSORS)
typedef struct thinkpad_softc {
device_t sc_dev;
@ -112,8 +114,10 @@ static ACPI_STATUS thinkpad_mask_init(thinkpad_softc_t *, uint32_t);
static void thinkpad_notify_handler(ACPI_HANDLE, UINT32, void *);
static void thinkpad_get_hotkeys(void *);
static void thinkpad_temp_init(thinkpad_softc_t *);
static void thinkpad_sensors_init(thinkpad_softc_t *);
static void thinkpad_sensors_refresh(struct sysmon_envsys *, envsys_data_t *);
static void thinkpad_temp_refresh(struct sysmon_envsys *, envsys_data_t *);
static void thinkpad_fan_refresh(struct sysmon_envsys *, envsys_data_t *);
static void thinkpad_wireless_toggle(thinkpad_softc_t *);
@ -252,8 +256,8 @@ thinkpad_attach(device_t parent, device_t self, void *opaque)
}
}
/* Register temperature sensors with envsys */
thinkpad_temp_init(sc);
/* Register temperature and fan sensors with envsys */
thinkpad_sensors_init(sc);
fail:
if (!pmf_device_register(self, NULL, thinkpad_resume))
@ -433,16 +437,17 @@ thinkpad_mask_init(thinkpad_softc_t *sc, uint32_t mask)
}
static void
thinkpad_temp_init(thinkpad_softc_t *sc)
thinkpad_sensors_init(thinkpad_softc_t *sc)
{
char sname[5] = "TMP?";
int i, err;
char fname[5] = "FAN?";
int i, j, err;
if (sc->sc_ecdev == NULL)
return; /* no chance of this working */
sc->sc_sme = sysmon_envsys_create();
for (i = 0; i < THINKPAD_NSENSORS; i++) {
for (i = 0; i < THINKPAD_NTEMPSENSORS; i++) {
sname[3] = '0' + i;
strcpy(sc->sc_sensor[i].desc, sname);
sc->sc_sensor[i].units = ENVSYS_STEMP;
@ -451,10 +456,20 @@ thinkpad_temp_init(thinkpad_softc_t *sc)
aprint_error_dev(sc->sc_dev,
"couldn't attach sensor %s\n", sname);
}
j = i; /* THINKPAD_NTEMPSENSORS */
for (; i < (j + THINKPAD_NFANSENSORS); i++) {
fname[3] = '0' + (i - j);
strcpy(sc->sc_sensor[i].desc, fname);
sc->sc_sensor[i].units = ENVSYS_SFANRPM;
if (sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor[i]))
aprint_error_dev(sc->sc_dev,
"couldn't attach sensor %s\n", fname);
}
sc->sc_sme->sme_name = device_xname(sc->sc_dev);
sc->sc_sme->sme_cookie = sc;
sc->sc_sme->sme_refresh = thinkpad_temp_refresh;
sc->sc_sme->sme_refresh = thinkpad_sensors_refresh;
err = sysmon_envsys_register(sc->sc_sme);
if (err) {
@ -464,6 +479,21 @@ thinkpad_temp_init(thinkpad_softc_t *sc)
}
}
static void
thinkpad_sensors_refresh(struct sysmon_envsys *sme, envsys_data_t *edata)
{
switch (edata->units) {
case ENVSYS_STEMP:
thinkpad_temp_refresh(sme, edata);
break;
case ENVSYS_SFANRPM:
thinkpad_fan_refresh(sme, edata);
break;
default:
break;
}
}
static void
thinkpad_temp_refresh(struct sysmon_envsys *sme, envsys_data_t *edata)
{
@ -489,6 +519,42 @@ thinkpad_temp_refresh(struct sysmon_envsys *sme, envsys_data_t *edata)
edata->state = ENVSYS_SVALID;
}
static void
thinkpad_fan_refresh(struct sysmon_envsys *sme, envsys_data_t *edata)
{
thinkpad_softc_t *sc = sme->sme_cookie;
ACPI_INTEGER lo;
ACPI_INTEGER hi;
ACPI_STATUS rv;
int rpm;
/*
* Read the low byte first to avoid a firmware bug.
*/
rv = acpiec_bus_read(sc->sc_ecdev, 0x84, &lo, 1);
if (ACPI_FAILURE(rv)) {
edata->state = ENVSYS_SINVALID;
return;
}
rv = acpiec_bus_read(sc->sc_ecdev, 0x85, &hi, 1);
if (ACPI_FAILURE(rv)) {
edata->state = ENVSYS_SINVALID;
return;
}
rpm = ((((int)hi) << 8) | ((int)lo));
if (rpm < 0) {
edata->state = ENVSYS_SINVALID;
return;
}
edata->value_cur = rpm;
if (rpm < edata->value_min || edata->value_min == -1)
edata->value_min = rpm;
if (rpm > edata->value_max || edata->value_max == -1)
edata->value_max = rpm;
edata->state = ENVSYS_SVALID;
}
static void
thinkpad_wireless_toggle(thinkpad_softc_t *sc)
{