Rewrite the aibs(4) driver in order to support new models. Draws from the
revision 1.6 (claudio@) of the OpenBSD's equivalent driver. Tested by mrg@.
This commit is contained in:
parent
4ae6ef6285
commit
ef74b36d13
|
@ -1,4 +1,4 @@
|
|||
.\" $NetBSD: aibs.4,v 1.6 2010/03/06 19:53:33 cnst Exp $
|
||||
.\" $NetBSD: aibs.4,v 1.7 2011/06/12 07:25:43 jruoho Exp $
|
||||
.\" $OpenBSD: aibs.4,v 1.4 2009/07/30 06:30:45 jmc Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2009 Constantine A. Murenin <cnst+netbsd@bugmail.mojo.ru>
|
||||
|
@ -15,24 +15,21 @@
|
|||
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
.\"
|
||||
.Dd February 8, 2010
|
||||
.Dd June 12, 2011
|
||||
.Dt AIBS 4
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm aibs
|
||||
.Nd ASUSTeK AI Booster ACPI ATK0110 voltage, temperature, and fan sensor
|
||||
.Nd ASUSTeK AI Booster voltage, temperature, and fan sensor
|
||||
.Sh SYNOPSIS
|
||||
.Cd "aibs* at acpi?"
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
driver provides support for the voltage, temperature and fan sensors
|
||||
available through the
|
||||
.Tn ATK0110
|
||||
.Tn ASOC
|
||||
driver provides support for voltage, temperature, and fan sensors
|
||||
available as an
|
||||
.Tn ACPI
|
||||
device
|
||||
on
|
||||
device on
|
||||
.Tn ASUSTeK
|
||||
motherboards.
|
||||
The number of sensors of each type,
|
||||
|
@ -53,43 +50,43 @@ sensor states as follows:
|
|||
.Bl -bullet
|
||||
.It
|
||||
Voltage sensors can have a state of
|
||||
.Dv valid ,
|
||||
.Dv critunder ,
|
||||
.Sq valid ,
|
||||
.Sq critunder ,
|
||||
or
|
||||
.Dv critover ;
|
||||
.Sq critover ;
|
||||
temperature sensors can have a state of
|
||||
.Dv valid ,
|
||||
.Dv warnover ,
|
||||
.Dv critover ,
|
||||
.Sq valid ,
|
||||
.Sq warnover ,
|
||||
.Sq critover ,
|
||||
or
|
||||
.Dv invalid ;
|
||||
.Sq invalid ;
|
||||
and fan sensors can have a state of
|
||||
.Dv valid ,
|
||||
.Dv warnunder ,
|
||||
.Sq valid ,
|
||||
.Sq warnunder ,
|
||||
or
|
||||
.Dv warnover .
|
||||
.Sq warnover .
|
||||
.It
|
||||
Temperature sensors that have a reading of 0
|
||||
are marked
|
||||
.Dv invalid ,
|
||||
.Sq invalid ,
|
||||
whereas all other sensors are always assumed valid.
|
||||
.It
|
||||
Voltage sensors have a lower and an upper limit
|
||||
.Dv ( critunder
|
||||
Voltage sensors have a lower and an upper limit,
|
||||
.Sq critunder
|
||||
and
|
||||
.Dv critover ) ,
|
||||
temperature sensors have two upper limits
|
||||
.Dv ( warnover
|
||||
.Sq critover ,
|
||||
temperature sensors have two upper limits,
|
||||
.Sq warnover
|
||||
and
|
||||
.Dv critover ) ,
|
||||
.Sq critover ,
|
||||
whereas fan sensors may either have only the lower limit
|
||||
.Dv ( warnunder ) ,
|
||||
or, depending on the
|
||||
.Tn DSDT ,
|
||||
one lower and one upper limit
|
||||
.Dv ( warnunder
|
||||
.Sq warnunder ,
|
||||
or, depending on the vendor's
|
||||
.Tn ACPI
|
||||
implementation, one lower and one upper limit,
|
||||
.Sq warnunder
|
||||
and
|
||||
.Dv warnover ) .
|
||||
.Sq warnover .
|
||||
.El
|
||||
.Pp
|
||||
Sensor values and limits are made available through the
|
||||
|
@ -189,6 +186,7 @@ is configured and the system potentially supports
|
|||
the hardware monitoring chip through
|
||||
.Tn ACPI .
|
||||
.Sh SEE ALSO
|
||||
.Xr acpi 4 ,
|
||||
.Xr envsys 4 ,
|
||||
.Xr envstat 8
|
||||
.Sh HISTORY
|
||||
|
@ -199,8 +197,7 @@ driver first appeared in
|
|||
DragonFly 2.4.1
|
||||
and
|
||||
.Nx 6.0 .
|
||||
.Pp
|
||||
An earlier version of the driver,
|
||||
An earlier version of the driver, named
|
||||
.Nm aiboost ,
|
||||
first appeared in
|
||||
.Fx 7.0
|
||||
|
@ -212,16 +209,19 @@ The
|
|||
.Nm
|
||||
driver was written for
|
||||
.Ox ,
|
||||
DragonFly
|
||||
and
|
||||
DragonFly BSD, and
|
||||
.Nx
|
||||
by
|
||||
.An Constantine A. Murenin Aq http://cnst.su/ ,
|
||||
Raouf Boutaba Research Group,
|
||||
David R. Cheriton School of Computer Science,
|
||||
University of Waterloo.
|
||||
.Pp
|
||||
An earlier version of the driver, named
|
||||
.An Jukka Ruohonen
|
||||
.Aq jruohonen@iki.fi
|
||||
later reworked and adjusted the driver to support new
|
||||
.Tn ASUSTeK
|
||||
motherboards.
|
||||
The earlier version of the driver,
|
||||
.Nm aiboost ,
|
||||
was written for
|
||||
.Fx
|
||||
|
|
|
@ -0,0 +1,742 @@
|
|||
/* $NetBSD: aibs_acpi.c,v 1.1 2011/06/12 07:25:43 jruoho Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2011 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Jukka Ruohonen.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* $OpenBSD: atk0110.c,v 1.1 2009/07/23 01:38:16 cnst Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2009 Constantine A. Murenin <cnst+netbsd@bugmail.mojo.ru>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: aibs_acpi.c,v 1.1 2011/06/12 07:25:43 jruoho Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kmem.h>
|
||||
#include <sys/module.h>
|
||||
|
||||
#include <dev/acpi/acpireg.h>
|
||||
#include <dev/acpi/acpivar.h>
|
||||
|
||||
/*
|
||||
* ASUSTeK AI Booster (ACPI ASOC ATK0110).
|
||||
*
|
||||
* This code was originally written for OpenBSD after the techniques
|
||||
* described in the Linux's asus_atk0110.c and FreeBSD's acpi_aiboost.c
|
||||
* were verified to be accurate on the actual hardware kindly provided by
|
||||
* Sam Fourman Jr. It was subsequently ported from OpenBSD to DragonFly BSD,
|
||||
* and then to the NetBSD's sysmon_envsys(9) framework.
|
||||
*
|
||||
* -- Constantine A. Murenin <http://cnst.su/>
|
||||
*/
|
||||
|
||||
#define _COMPONENT ACPI_RESOURCE_COMPONENT
|
||||
ACPI_MODULE_NAME ("acpi_aibs")
|
||||
|
||||
#define AIBS_MUX_HWMON 0x00000006
|
||||
#define AIBS_MUX_MGMT 0x00000011
|
||||
|
||||
#define AIBS_TYPE(x) (((x) >> 16) & 0xff)
|
||||
#define AIBS_TYPE_VOLT 2
|
||||
#define AIBS_TYPE_TEMP 3
|
||||
#define AIBS_TYPE_FAN 4
|
||||
|
||||
struct aibs_sensor {
|
||||
envsys_data_t as_sensor;
|
||||
uint64_t as_type;
|
||||
uint64_t as_liml;
|
||||
uint64_t as_limh;
|
||||
|
||||
SIMPLEQ_ENTRY(aibs_sensor) as_list;
|
||||
};
|
||||
|
||||
struct aibs_softc {
|
||||
device_t sc_dev;
|
||||
struct acpi_devnode *sc_node;
|
||||
struct sysmon_envsys *sc_sme;
|
||||
bool sc_model; /* new model = true */
|
||||
|
||||
SIMPLEQ_HEAD(, aibs_sensor) as_head;
|
||||
};
|
||||
|
||||
static int aibs_match(device_t, cfdata_t, void *);
|
||||
static void aibs_attach(device_t, device_t, void *);
|
||||
static int aibs_detach(device_t, int);
|
||||
|
||||
static void aibs_init(device_t);
|
||||
static void aibs_init_new(device_t);
|
||||
static void aibs_init_old(device_t, int);
|
||||
|
||||
static void aibs_sensor_add(device_t, ACPI_OBJECT *);
|
||||
static bool aibs_sensor_value(device_t, struct aibs_sensor *, uint64_t *);
|
||||
static void aibs_sensor_refresh(struct sysmon_envsys *, envsys_data_t *);
|
||||
static void aibs_sensor_limits(struct sysmon_envsys *, envsys_data_t *,
|
||||
sysmon_envsys_lim_t *, uint32_t *);
|
||||
|
||||
CFATTACH_DECL_NEW(aibs, sizeof(struct aibs_softc),
|
||||
aibs_match, aibs_attach, aibs_detach, NULL);
|
||||
|
||||
static const char* const aibs_hid[] = {
|
||||
"ATK0110",
|
||||
NULL
|
||||
};
|
||||
|
||||
static int
|
||||
aibs_match(device_t parent, cfdata_t match, void *aux)
|
||||
{
|
||||
struct acpi_attach_args *aa = aux;
|
||||
|
||||
if (aa->aa_node->ad_type != ACPI_TYPE_DEVICE)
|
||||
return 0;
|
||||
|
||||
return acpi_match_hid(aa->aa_node->ad_devinfo, aibs_hid);
|
||||
}
|
||||
|
||||
static void
|
||||
aibs_attach(device_t parent, device_t self, void *aux)
|
||||
{
|
||||
struct aibs_softc *sc = device_private(self);
|
||||
struct acpi_attach_args *aa = aux;
|
||||
|
||||
sc->sc_dev = self;
|
||||
sc->sc_node = aa->aa_node;
|
||||
|
||||
aprint_naive("\n");
|
||||
aprint_normal(": ASUSTeK AI Booster\n");
|
||||
|
||||
sc->sc_sme = sysmon_envsys_create();
|
||||
|
||||
sc->sc_sme->sme_cookie = sc;
|
||||
sc->sc_sme->sme_name = device_xname(self);
|
||||
sc->sc_sme->sme_refresh = aibs_sensor_refresh;
|
||||
sc->sc_sme->sme_get_limits = aibs_sensor_limits;
|
||||
|
||||
aibs_init(self);
|
||||
SIMPLEQ_INIT(&sc->as_head);
|
||||
|
||||
if (sc->sc_model != false)
|
||||
aibs_init_new(self);
|
||||
else {
|
||||
aibs_init_old(self, AIBS_TYPE_FAN);
|
||||
aibs_init_old(self, AIBS_TYPE_TEMP);
|
||||
aibs_init_old(self, AIBS_TYPE_VOLT);
|
||||
}
|
||||
|
||||
(void)pmf_device_register(self, NULL, NULL);
|
||||
|
||||
if (sc->sc_sme->sme_nsensors == 0) {
|
||||
aprint_error_dev(self, "no sensors found\n");
|
||||
sysmon_envsys_destroy(sc->sc_sme);
|
||||
sc->sc_sme = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
if (sysmon_envsys_register(sc->sc_sme) != 0)
|
||||
aprint_error_dev(self, "failed to register with sysmon\n");
|
||||
}
|
||||
|
||||
static int
|
||||
aibs_detach(device_t self, int flags)
|
||||
{
|
||||
struct aibs_softc *sc = device_private(self);
|
||||
struct aibs_sensor *as;
|
||||
|
||||
pmf_device_deregister(self);
|
||||
|
||||
if (sc->sc_sme != NULL)
|
||||
sysmon_envsys_unregister(sc->sc_sme);
|
||||
|
||||
while (SIMPLEQ_FIRST(&sc->as_head) != NULL) {
|
||||
as = SIMPLEQ_FIRST(&sc->as_head);
|
||||
SIMPLEQ_REMOVE_HEAD(&sc->as_head, as_list);
|
||||
kmem_free(as, sizeof(*as));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
aibs_init(device_t self)
|
||||
{
|
||||
struct aibs_softc *sc = device_private(self);
|
||||
ACPI_HANDLE tmp;
|
||||
ACPI_STATUS rv;
|
||||
|
||||
/*
|
||||
* Old model uses the tuple { TSIF, VSIF, FSIF } to
|
||||
* enumerate the sensors and { RTMP, RVLT, RFAN }
|
||||
* to obtain the values. New mode uses GGRP for the
|
||||
* enumeration and { GITM, SITM } as accessors.
|
||||
*/
|
||||
rv = AcpiGetHandle(sc->sc_node->ad_handle, "GGRP", &tmp);
|
||||
|
||||
if (ACPI_FAILURE(rv)) {
|
||||
sc->sc_model = false;
|
||||
return;
|
||||
}
|
||||
|
||||
rv = AcpiGetHandle(sc->sc_node->ad_handle, "GITM", &tmp);
|
||||
|
||||
if (ACPI_FAILURE(rv)) {
|
||||
sc->sc_model = false;
|
||||
return;
|
||||
}
|
||||
|
||||
rv = AcpiGetHandle(sc->sc_node->ad_handle, "SITM", &tmp);
|
||||
|
||||
if (ACPI_FAILURE(rv)) {
|
||||
sc->sc_model = false;
|
||||
return;
|
||||
}
|
||||
|
||||
sc->sc_model = true;
|
||||
}
|
||||
|
||||
static void
|
||||
aibs_init_new(device_t self)
|
||||
{
|
||||
struct aibs_softc *sc = device_private(self);
|
||||
ACPI_OBJECT_LIST arg;
|
||||
ACPI_OBJECT id, *obj;
|
||||
ACPI_BUFFER buf;
|
||||
ACPI_STATUS rv;
|
||||
uint32_t i, n;
|
||||
|
||||
arg.Count = 1;
|
||||
arg.Pointer = &id;
|
||||
|
||||
id.Type = ACPI_TYPE_INTEGER;
|
||||
id.Integer.Value = AIBS_MUX_HWMON;
|
||||
|
||||
buf.Pointer = NULL;
|
||||
buf.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
|
||||
|
||||
rv = AcpiEvaluateObject(sc->sc_node->ad_handle, "GGRP", &arg, &buf);
|
||||
|
||||
if (ACPI_FAILURE(rv))
|
||||
goto out;
|
||||
|
||||
obj = buf.Pointer;
|
||||
|
||||
if (obj->Type != ACPI_TYPE_PACKAGE) {
|
||||
rv = AE_TYPE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (obj->Package.Count > UINT32_MAX) {
|
||||
rv = AE_AML_NUMERIC_OVERFLOW;
|
||||
goto out;
|
||||
}
|
||||
|
||||
n = obj->Package.Count;
|
||||
|
||||
if (n == 0) {
|
||||
rv = AE_NOT_EXIST;
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
aibs_sensor_add(self, &obj->Package.Elements[i]);
|
||||
|
||||
out:
|
||||
if (buf.Pointer != NULL)
|
||||
ACPI_FREE(buf.Pointer);
|
||||
|
||||
if (ACPI_FAILURE(rv)) {
|
||||
|
||||
aprint_error_dev(self, "failed to evaluate "
|
||||
"GGRP: %s\n", AcpiFormatException(rv));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
aibs_init_old(device_t self, int type)
|
||||
{
|
||||
struct aibs_softc *sc = device_private(self);
|
||||
char path[] = "?SIF";
|
||||
ACPI_OBJECT *elm, *obj;
|
||||
ACPI_BUFFER buf;
|
||||
ACPI_STATUS rv;
|
||||
uint32_t i, n;
|
||||
|
||||
switch (type) {
|
||||
|
||||
case AIBS_TYPE_FAN:
|
||||
path[0] = 'F';
|
||||
break;
|
||||
|
||||
case AIBS_TYPE_TEMP:
|
||||
path[0] = 'T';
|
||||
break;
|
||||
|
||||
case AIBS_TYPE_VOLT:
|
||||
path[0] = 'V';
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
rv = acpi_eval_struct(sc->sc_node->ad_handle, path, &buf);
|
||||
|
||||
if (ACPI_FAILURE(rv))
|
||||
goto out;
|
||||
|
||||
obj = buf.Pointer;
|
||||
|
||||
if (obj->Type != ACPI_TYPE_PACKAGE) {
|
||||
rv = AE_TYPE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
elm = obj->Package.Elements;
|
||||
|
||||
if (elm[0].Type != ACPI_TYPE_INTEGER) {
|
||||
rv = AE_TYPE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (elm[0].Integer.Value > UINT32_MAX) {
|
||||
rv = AE_AML_NUMERIC_OVERFLOW;
|
||||
goto out;
|
||||
}
|
||||
|
||||
n = elm[0].Integer.Value;
|
||||
|
||||
if (n == 0) {
|
||||
rv = AE_NOT_EXIST;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (obj->Package.Count - 1 != n) {
|
||||
rv = AE_BAD_VALUE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (i = 1; i < obj->Package.Count; i++) {
|
||||
|
||||
if (elm[i].Type != ACPI_TYPE_PACKAGE)
|
||||
continue;
|
||||
|
||||
aibs_sensor_add(self, &elm[i]);
|
||||
}
|
||||
|
||||
out:
|
||||
if (buf.Pointer != NULL)
|
||||
ACPI_FREE(buf.Pointer);
|
||||
|
||||
if (ACPI_FAILURE(rv)) {
|
||||
|
||||
aprint_error_dev(self, "failed to evaluate "
|
||||
"%s: %s\n", path, AcpiFormatException(rv));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
aibs_sensor_add(device_t self, ACPI_OBJECT *obj)
|
||||
{
|
||||
struct aibs_softc *sc = device_private(self);
|
||||
struct aibs_sensor *as;
|
||||
int ena, len, lhi, llo;
|
||||
const char *name;
|
||||
ACPI_STATUS rv;
|
||||
|
||||
as = NULL;
|
||||
rv = AE_OK;
|
||||
|
||||
if (obj->Type != ACPI_TYPE_PACKAGE) {
|
||||
rv = AE_TYPE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* The known formats are:
|
||||
*
|
||||
* index type old new
|
||||
* ----- ---- --- ---
|
||||
* 0 integer flags flags
|
||||
* 1 string name name
|
||||
* 2 integer limit1 unknown
|
||||
* 3 integer limit2 unknown
|
||||
* 4 integer enable limit1
|
||||
* 5 integer - limit2
|
||||
* 6 integer - enable
|
||||
*/
|
||||
if (sc->sc_model != false) {
|
||||
len = 7;
|
||||
llo = 4;
|
||||
lhi = 5;
|
||||
ena = 6;
|
||||
} else {
|
||||
len = 5;
|
||||
llo = 2;
|
||||
lhi = 3;
|
||||
ena = 4;
|
||||
}
|
||||
|
||||
if (obj->Package.Count != (uint32_t)len) {
|
||||
rv = AE_LIMIT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (obj->Package.Elements[0].Type != ACPI_TYPE_INTEGER ||
|
||||
obj->Package.Elements[1].Type != ACPI_TYPE_STRING ||
|
||||
obj->Package.Elements[llo].Type != ACPI_TYPE_INTEGER ||
|
||||
obj->Package.Elements[lhi].Type != ACPI_TYPE_INTEGER ||
|
||||
obj->Package.Elements[ena].Type != ACPI_TYPE_INTEGER) {
|
||||
rv = AE_TYPE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
as = kmem_zalloc(sizeof(*as), KM_SLEEP);
|
||||
|
||||
if (as == NULL) {
|
||||
rv = AE_NO_MEMORY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
name = obj->Package.Elements[1].String.Pointer;
|
||||
|
||||
as->as_type = obj->Package.Elements[0].Integer.Value;
|
||||
as->as_liml = obj->Package.Elements[llo].Integer.Value;
|
||||
as->as_limh = obj->Package.Elements[lhi].Integer.Value;
|
||||
|
||||
if (sc->sc_model != false)
|
||||
as->as_limh += as->as_liml; /* A range in the new model. */
|
||||
|
||||
switch (AIBS_TYPE(as->as_type)) {
|
||||
|
||||
case AIBS_TYPE_FAN:
|
||||
as->as_sensor.units = ENVSYS_SFANRPM;
|
||||
as->as_sensor.flags |= ENVSYS_FMONLIMITS;
|
||||
break;
|
||||
|
||||
case AIBS_TYPE_TEMP:
|
||||
as->as_sensor.units = ENVSYS_STEMP;
|
||||
as->as_sensor.flags |= ENVSYS_FMONLIMITS;
|
||||
break;
|
||||
|
||||
case AIBS_TYPE_VOLT:
|
||||
as->as_sensor.units = ENVSYS_SVOLTS_DC;
|
||||
as->as_sensor.flags |= ENVSYS_FMONLIMITS;
|
||||
break;
|
||||
|
||||
default:
|
||||
rv = AE_TYPE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
(void)strlcpy(as->as_sensor.desc, name, sizeof(as->as_sensor.desc));
|
||||
|
||||
if (sysmon_envsys_sensor_attach(sc->sc_sme, &as->as_sensor) != 0) {
|
||||
rv = AE_AML_INTERNAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
SIMPLEQ_INSERT_TAIL(&sc->as_head, as, as_list);
|
||||
|
||||
out:
|
||||
if (ACPI_FAILURE(rv)) {
|
||||
|
||||
if (as != NULL)
|
||||
kmem_free(as, sizeof(*as));
|
||||
|
||||
aprint_error_dev(self, "failed to add "
|
||||
"sensor: %s\n", AcpiFormatException(rv));
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
aibs_sensor_value(device_t self, struct aibs_sensor *as, uint64_t *val)
|
||||
{
|
||||
struct aibs_softc *sc = device_private(self);
|
||||
uint32_t type, *ret, cmb[3];
|
||||
ACPI_OBJECT_LIST arg;
|
||||
ACPI_OBJECT cmi, tmp;
|
||||
ACPI_OBJECT *obj;
|
||||
ACPI_BUFFER buf;
|
||||
ACPI_STATUS rv;
|
||||
const char *path;
|
||||
|
||||
if (sc->sc_model != false) {
|
||||
|
||||
path = "GITM";
|
||||
|
||||
cmb[0] = as->as_type;
|
||||
cmb[1] = 0;
|
||||
cmb[2] = 0;
|
||||
|
||||
arg.Count = 1;
|
||||
arg.Pointer = &tmp;
|
||||
|
||||
tmp.Buffer.Length = sizeof(cmb);
|
||||
tmp.Buffer.Pointer = (uint8_t *)cmb;
|
||||
tmp.Type = type = ACPI_TYPE_BUFFER;
|
||||
|
||||
} else {
|
||||
|
||||
arg.Count = 1;
|
||||
arg.Pointer = &cmi;
|
||||
|
||||
cmi.Integer.Value = as->as_type;
|
||||
cmi.Type = type = ACPI_TYPE_INTEGER;
|
||||
|
||||
switch (AIBS_TYPE(as->as_type)) {
|
||||
|
||||
case AIBS_TYPE_FAN:
|
||||
path = "RFAN";
|
||||
break;
|
||||
|
||||
case AIBS_TYPE_TEMP:
|
||||
path = "RTMP";
|
||||
break;
|
||||
|
||||
case AIBS_TYPE_VOLT:
|
||||
path = "RVLT";
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
buf.Pointer = NULL;
|
||||
buf.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
|
||||
|
||||
rv = AcpiEvaluateObject(sc->sc_node->ad_handle, path, &arg, &buf);
|
||||
|
||||
if (ACPI_FAILURE(rv))
|
||||
goto out;
|
||||
|
||||
obj = buf.Pointer;
|
||||
|
||||
if (obj->Type != type) {
|
||||
rv = AE_TYPE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (sc->sc_model != true)
|
||||
*val = obj->Integer.Value;
|
||||
else {
|
||||
/*
|
||||
* The return buffer contains at least:
|
||||
*
|
||||
* uint32_t buf[0] flags
|
||||
* uint32_t buf[1] return value
|
||||
* uint8_t buf[2-] unknown
|
||||
*/
|
||||
if (obj->Buffer.Length < 8) {
|
||||
rv = AE_BUFFER_OVERFLOW;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = (uint32_t *)obj->Buffer.Pointer;
|
||||
|
||||
if (ret[0] == 0) {
|
||||
rv = AE_BAD_VALUE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
*val = ret[1];
|
||||
}
|
||||
|
||||
out:
|
||||
if (buf.Pointer != NULL)
|
||||
ACPI_FREE(buf.Pointer);
|
||||
|
||||
if (ACPI_FAILURE(rv)) {
|
||||
|
||||
aprint_error_dev(self, "failed to evaluate "
|
||||
"%s: %s\n", path, AcpiFormatException(rv));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
aibs_sensor_refresh(struct sysmon_envsys *sme, envsys_data_t *edata)
|
||||
{
|
||||
struct aibs_softc *sc = sme->sme_cookie;
|
||||
struct aibs_sensor *tmp, *as = NULL;
|
||||
envsys_data_t *s = edata;
|
||||
uint64_t val = 0;
|
||||
|
||||
SIMPLEQ_FOREACH(tmp, &sc->as_head, as_list) {
|
||||
|
||||
if (tmp->as_sensor.sensor == s->sensor) {
|
||||
as = tmp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (as == NULL) {
|
||||
aprint_debug_dev(sc->sc_dev, "failed to find sensor\n");
|
||||
return;
|
||||
}
|
||||
|
||||
as->as_sensor.state = ENVSYS_SINVALID;
|
||||
as->as_sensor.flags |= ENVSYS_FMONNOTSUPP;
|
||||
|
||||
if (aibs_sensor_value(sc->sc_dev, as, &val) != true)
|
||||
return;
|
||||
|
||||
switch (as->as_sensor.units) {
|
||||
|
||||
case ENVSYS_SFANRPM:
|
||||
as->as_sensor.value_cur = val;
|
||||
break;
|
||||
|
||||
case ENVSYS_STEMP:
|
||||
|
||||
if (val == 0)
|
||||
return;
|
||||
|
||||
as->as_sensor.value_cur = val * 100 * 1000 + 273150000;
|
||||
break;
|
||||
|
||||
case ENVSYS_SVOLTS_DC:
|
||||
as->as_sensor.value_cur = val * 1000;
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
as->as_sensor.state = ENVSYS_SVALID;
|
||||
as->as_sensor.flags &= ~ENVSYS_FMONNOTSUPP;
|
||||
}
|
||||
|
||||
static void
|
||||
aibs_sensor_limits(struct sysmon_envsys *sme, envsys_data_t *edata,
|
||||
sysmon_envsys_lim_t *limits, uint32_t *props)
|
||||
{
|
||||
struct aibs_softc *sc = sme->sme_cookie;
|
||||
struct aibs_sensor *tmp, *as = NULL;
|
||||
sysmon_envsys_lim_t *lim = limits;
|
||||
envsys_data_t *s = edata;
|
||||
|
||||
SIMPLEQ_FOREACH(tmp, &sc->as_head, as_list) {
|
||||
|
||||
if (tmp->as_sensor.sensor == s->sensor) {
|
||||
as = tmp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (as == NULL) {
|
||||
aprint_debug_dev(sc->sc_dev, "failed to find sensor\n");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (as->as_sensor.units) {
|
||||
|
||||
case ENVSYS_SFANRPM:
|
||||
|
||||
/*
|
||||
* Some boards have strange limits for fans.
|
||||
*/
|
||||
if (as->as_liml == 0) {
|
||||
lim->sel_warnmin = as->as_limh;
|
||||
*props = PROP_WARNMIN;
|
||||
|
||||
} else {
|
||||
lim->sel_warnmin = as->as_liml;
|
||||
lim->sel_warnmax = as->as_limh;
|
||||
*props = PROP_WARNMIN | PROP_WARNMAX;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case ENVSYS_STEMP:
|
||||
lim->sel_critmax = as->as_limh * 100 * 1000 + 273150000;
|
||||
lim->sel_warnmax = as->as_liml * 100 * 1000 + 273150000;
|
||||
|
||||
*props = PROP_CRITMAX | PROP_WARNMAX;
|
||||
break;
|
||||
|
||||
case ENVSYS_SVOLTS_DC:
|
||||
lim->sel_critmin = as->as_liml * 1000;
|
||||
lim->sel_critmax = as->as_limh * 1000;
|
||||
*props = PROP_CRITMIN | PROP_CRITMAX;
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
MODULE(MODULE_CLASS_DRIVER, aibs, NULL);
|
||||
|
||||
#ifdef _MODULE
|
||||
#include "ioconf.c"
|
||||
#endif
|
||||
|
||||
static int
|
||||
aibs_modcmd(modcmd_t cmd, void *aux)
|
||||
{
|
||||
int rv = 0;
|
||||
|
||||
switch (cmd) {
|
||||
|
||||
case MODULE_CMD_INIT:
|
||||
|
||||
#ifdef _MODULE
|
||||
rv = config_init_component(cfdriver_ioconf_aibs,
|
||||
cfattach_ioconf_aibs, cfdata_ioconf_aibs);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case MODULE_CMD_FINI:
|
||||
|
||||
#ifdef _MODULE
|
||||
rv = config_fini_component(cfdriver_ioconf_aibs,
|
||||
cfattach_ioconf_aibs, cfdata_ioconf_aibs);
|
||||
#endif
|
||||
break;
|
||||
|
||||
default:
|
||||
rv = ENOTTY;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
|
@ -1,458 +0,0 @@
|
|||
/* $NetBSD: atk0110.c,v 1.16 2011/02/16 09:05:12 jruoho Exp $ */
|
||||
/* $OpenBSD: atk0110.c,v 1.1 2009/07/23 01:38:16 cnst Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2009 Constantine A. Murenin <cnst+netbsd@bugmail.mojo.ru>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: atk0110.c,v 1.16 2011/02/16 09:05:12 jruoho Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kmem.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/systm.h>
|
||||
|
||||
#include <dev/acpi/acpireg.h>
|
||||
#include <dev/acpi/acpivar.h>
|
||||
|
||||
/*
|
||||
* ASUSTeK AI Booster (ACPI ASOC ATK0110).
|
||||
*
|
||||
* This code was originally written for OpenBSD after the techniques
|
||||
* described in the Linux's asus_atk0110.c and FreeBSD's acpi_aiboost.c
|
||||
* were verified to be accurate on the actual hardware kindly provided by
|
||||
* Sam Fourman Jr. It was subsequently ported from OpenBSD to DragonFly BSD,
|
||||
* and then to the NetBSD's sysmon_envsys(9) framework.
|
||||
*
|
||||
* -- Constantine A. Murenin <http://cnst.su/>
|
||||
*/
|
||||
|
||||
#define _COMPONENT ACPI_RESOURCE_COMPONENT
|
||||
ACPI_MODULE_NAME ("acpi_aibs")
|
||||
|
||||
struct aibs_sensor {
|
||||
envsys_data_t s;
|
||||
ACPI_INTEGER i;
|
||||
ACPI_INTEGER l;
|
||||
ACPI_INTEGER h;
|
||||
};
|
||||
|
||||
struct aibs_softc {
|
||||
struct acpi_devnode *sc_node;
|
||||
struct sysmon_envsys *sc_sme;
|
||||
struct aibs_sensor *sc_asens_volt;
|
||||
struct aibs_sensor *sc_asens_temp;
|
||||
struct aibs_sensor *sc_asens_fan;
|
||||
uint32_t sc_asens_volt_count;
|
||||
uint32_t sc_asens_temp_count;
|
||||
uint32_t sc_asens_fan_count;
|
||||
};
|
||||
|
||||
static int aibs_match(device_t, cfdata_t, void *);
|
||||
static void aibs_attach(device_t, device_t, void *);
|
||||
static int aibs_detach(device_t, int);
|
||||
static void aibs_refresh(struct sysmon_envsys *, envsys_data_t *);
|
||||
static void aibs_get_limits(struct sysmon_envsys *, envsys_data_t *,
|
||||
sysmon_envsys_lim_t *, uint32_t *);
|
||||
|
||||
static void aibs_attach_sif(device_t, enum envsys_units);
|
||||
|
||||
CFATTACH_DECL_NEW(aibs, sizeof(struct aibs_softc),
|
||||
aibs_match, aibs_attach, aibs_detach, NULL);
|
||||
|
||||
static const char* const aibs_hid[] = {
|
||||
"ATK0110",
|
||||
NULL
|
||||
};
|
||||
|
||||
static int
|
||||
aibs_match(device_t parent, cfdata_t match, void *aux)
|
||||
{
|
||||
struct acpi_attach_args *aa = aux;
|
||||
|
||||
if(aa->aa_node->ad_type != ACPI_TYPE_DEVICE)
|
||||
return 0;
|
||||
|
||||
return acpi_match_hid(aa->aa_node->ad_devinfo, aibs_hid);
|
||||
}
|
||||
|
||||
static void
|
||||
aibs_attach(device_t parent, device_t self, void *aux)
|
||||
{
|
||||
struct aibs_softc *sc = device_private(self);
|
||||
struct acpi_attach_args *aa = aux;
|
||||
|
||||
sc->sc_node = aa->aa_node;
|
||||
|
||||
aprint_naive(": ASUSTeK AI Booster\n");
|
||||
aprint_normal(": ASUSTeK AI Booster\n");
|
||||
|
||||
sc->sc_sme = sysmon_envsys_create();
|
||||
sc->sc_sme->sme_name = device_xname(self);
|
||||
sc->sc_sme->sme_cookie = sc;
|
||||
sc->sc_sme->sme_refresh = aibs_refresh;
|
||||
sc->sc_sme->sme_get_limits = aibs_get_limits;
|
||||
|
||||
aibs_attach_sif(self, ENVSYS_SVOLTS_DC);
|
||||
aibs_attach_sif(self, ENVSYS_STEMP);
|
||||
aibs_attach_sif(self, ENVSYS_SFANRPM);
|
||||
|
||||
(void)pmf_device_register(self, NULL, NULL);
|
||||
|
||||
if (sc->sc_sme->sme_nsensors == 0) {
|
||||
aprint_error_dev(self, "no sensors found\n");
|
||||
sysmon_envsys_destroy(sc->sc_sme);
|
||||
return;
|
||||
}
|
||||
|
||||
if (sysmon_envsys_register(sc->sc_sme) != 0)
|
||||
aprint_error_dev(self, "failed to register with sysmon\n");
|
||||
}
|
||||
|
||||
static void
|
||||
aibs_attach_sif(device_t self, enum envsys_units st)
|
||||
{
|
||||
struct aibs_softc *sc = device_private(self);
|
||||
ACPI_OBJECT *bp, *o, *oi;
|
||||
ACPI_BUFFER b;
|
||||
ACPI_STATUS rv;
|
||||
uint32_t i, n;
|
||||
char name[] = "?SIF";
|
||||
struct aibs_sensor *as;
|
||||
|
||||
switch (st) {
|
||||
|
||||
case ENVSYS_STEMP:
|
||||
name[0] = 'T';
|
||||
break;
|
||||
|
||||
case ENVSYS_SFANRPM:
|
||||
name[0] = 'F';
|
||||
break;
|
||||
|
||||
case ENVSYS_SVOLTS_DC:
|
||||
name[0] = 'V';
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
rv = acpi_eval_struct(sc->sc_node->ad_handle, name, &b);
|
||||
|
||||
if (ACPI_FAILURE(rv))
|
||||
goto out;
|
||||
|
||||
bp = b.Pointer;
|
||||
|
||||
if (bp->Type != ACPI_TYPE_PACKAGE) {
|
||||
rv = AE_TYPE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
o = bp->Package.Elements;
|
||||
|
||||
if (o[0].Type != ACPI_TYPE_INTEGER) {
|
||||
rv = AE_TYPE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (o[0].Integer.Value > UINT32_MAX) {
|
||||
rv = AE_AML_NUMERIC_OVERFLOW;
|
||||
goto out;
|
||||
}
|
||||
|
||||
n = o[0].Integer.Value;
|
||||
|
||||
if (n == 0) {
|
||||
rv = AE_LIMIT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (bp->Package.Count - 1 != n) {
|
||||
rv = AE_BAD_VALUE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
as = kmem_zalloc(sizeof(*as) * n, KM_SLEEP);
|
||||
|
||||
if (as == NULL) {
|
||||
rv = AE_NO_MEMORY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
switch (st) {
|
||||
|
||||
case ENVSYS_STEMP:
|
||||
sc->sc_asens_temp = as;
|
||||
sc->sc_asens_temp_count = n;
|
||||
break;
|
||||
|
||||
case ENVSYS_SFANRPM:
|
||||
sc->sc_asens_fan = as;
|
||||
sc->sc_asens_fan_count = n;
|
||||
break;
|
||||
|
||||
case ENVSYS_SVOLTS_DC:
|
||||
sc->sc_asens_volt = as;
|
||||
sc->sc_asens_volt_count = n;
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0, o++; i < n; i++, o++) {
|
||||
|
||||
if(o[0].Type != ACPI_TYPE_PACKAGE) {
|
||||
aprint_error_dev(self,
|
||||
"%s: %i: not a package: %u type\n",
|
||||
name, i, o[0].Type);
|
||||
continue;
|
||||
}
|
||||
oi = o[0].Package.Elements;
|
||||
if (o[0].Package.Count != 5 ||
|
||||
oi[0].Type != ACPI_TYPE_INTEGER ||
|
||||
oi[1].Type != ACPI_TYPE_STRING ||
|
||||
oi[2].Type != ACPI_TYPE_INTEGER ||
|
||||
oi[3].Type != ACPI_TYPE_INTEGER ||
|
||||
oi[4].Type != ACPI_TYPE_INTEGER) {
|
||||
aprint_error_dev(self,
|
||||
"%s: %i: invalid package\n",
|
||||
name, i);
|
||||
continue;
|
||||
}
|
||||
as[i].i = oi[0].Integer.Value;
|
||||
strlcpy(as[i].s.desc, oi[1].String.Pointer,
|
||||
sizeof(as[i].s.desc));
|
||||
as[i].l = oi[2].Integer.Value;
|
||||
as[i].h = oi[3].Integer.Value;
|
||||
as[i].s.units = st;
|
||||
as[i].s.flags |= ENVSYS_FMONLIMITS;
|
||||
aprint_verbose_dev(self, "%c%i: "
|
||||
"0x%08"PRIx64" %20s %5"PRIi64" / %5"PRIi64" "
|
||||
"0x%"PRIx64"\n",
|
||||
name[0], i,
|
||||
as[i].i, as[i].s.desc, (int64_t)as[i].l, (int64_t)as[i].h,
|
||||
oi[4].Integer.Value);
|
||||
if (sysmon_envsys_sensor_attach(sc->sc_sme, &as[i].s))
|
||||
aprint_error_dev(self, "%c%i: unable to attach\n",
|
||||
name[0], i);
|
||||
}
|
||||
|
||||
out:
|
||||
if (b.Pointer != NULL)
|
||||
ACPI_FREE(b.Pointer);
|
||||
|
||||
if (ACPI_FAILURE(rv))
|
||||
aprint_error_dev(self, "failed to evaluate %s: %s\n",
|
||||
name, AcpiFormatException(rv));
|
||||
}
|
||||
|
||||
static int
|
||||
aibs_detach(device_t self, int flags)
|
||||
{
|
||||
static const size_t size = sizeof(struct aibs_sensor);
|
||||
struct aibs_softc *sc = device_private(self);
|
||||
|
||||
pmf_device_deregister(self);
|
||||
sysmon_envsys_unregister(sc->sc_sme);
|
||||
|
||||
if (sc->sc_asens_volt != NULL)
|
||||
kmem_free(sc->sc_asens_volt, sc->sc_asens_volt_count * size);
|
||||
|
||||
if (sc->sc_asens_temp != NULL)
|
||||
kmem_free(sc->sc_asens_temp, sc->sc_asens_temp_count * size);
|
||||
|
||||
if (sc->sc_asens_fan != NULL)
|
||||
kmem_free(sc->sc_asens_fan, sc->sc_asens_fan_count * size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
aibs_refresh(struct sysmon_envsys *sme, envsys_data_t *edata)
|
||||
{
|
||||
struct aibs_softc *sc = sme->sme_cookie;
|
||||
device_t self = sc->sc_node->ad_device;
|
||||
envsys_data_t *s = edata;
|
||||
enum envsys_units st = s->units;
|
||||
ACPI_STATUS rs;
|
||||
ACPI_OBJECT p, *bp;
|
||||
ACPI_OBJECT_LIST mp;
|
||||
ACPI_BUFFER b;
|
||||
int i;
|
||||
const char *name;
|
||||
struct aibs_sensor *as;
|
||||
ACPI_INTEGER v;
|
||||
|
||||
switch (st) {
|
||||
case ENVSYS_STEMP:
|
||||
name = "RTMP";
|
||||
as = sc->sc_asens_temp;
|
||||
break;
|
||||
case ENVSYS_SFANRPM:
|
||||
name = "RFAN";
|
||||
as = sc->sc_asens_fan;
|
||||
break;
|
||||
case ENVSYS_SVOLTS_DC:
|
||||
name = "RVLT";
|
||||
as = sc->sc_asens_volt;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
if (as == NULL)
|
||||
return;
|
||||
for (i = 0; as[i].s.sensor != s->sensor; i++)
|
||||
;
|
||||
p.Type = ACPI_TYPE_INTEGER;
|
||||
p.Integer.Value = as[i].i;
|
||||
mp.Count = 1;
|
||||
mp.Pointer = &p;
|
||||
b.Length = ACPI_ALLOCATE_BUFFER;
|
||||
rs = AcpiEvaluateObjectTyped(sc->sc_node->ad_handle, name, &mp, &b,
|
||||
ACPI_TYPE_INTEGER);
|
||||
if (ACPI_FAILURE(rs)) {
|
||||
aprint_debug_dev(self,
|
||||
"%s: %i: evaluation failed\n",
|
||||
name, i);
|
||||
s->state = ENVSYS_SINVALID;
|
||||
s->flags |= ENVSYS_FMONNOTSUPP;
|
||||
return;
|
||||
}
|
||||
bp = b.Pointer;
|
||||
v = bp->Integer.Value;
|
||||
ACPI_FREE(b.Pointer);
|
||||
|
||||
switch (st) {
|
||||
case ENVSYS_STEMP:
|
||||
s->value_cur = v * 100 * 1000 + 273150000;
|
||||
if (v == 0) {
|
||||
s->state = ENVSYS_SINVALID;
|
||||
s->flags |= ENVSYS_FMONNOTSUPP;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case ENVSYS_SFANRPM:
|
||||
s->value_cur = v;
|
||||
break;
|
||||
case ENVSYS_SVOLTS_DC:
|
||||
s->value_cur = v * 1000;
|
||||
break;
|
||||
default:
|
||||
/* NOTREACHED */
|
||||
break;
|
||||
}
|
||||
if (s->state == 0 || s->state == ENVSYS_SINVALID)
|
||||
s->state = ENVSYS_SVALID;
|
||||
s->flags &= ~ENVSYS_FMONNOTSUPP;
|
||||
}
|
||||
|
||||
static void
|
||||
aibs_get_limits(struct sysmon_envsys *sme, envsys_data_t *edata,
|
||||
sysmon_envsys_lim_t *limits, uint32_t *props)
|
||||
{
|
||||
struct aibs_softc *sc = sme->sme_cookie;
|
||||
envsys_data_t *s = edata;
|
||||
sysmon_envsys_lim_t *li = limits;
|
||||
enum envsys_units st = s->units;
|
||||
int i;
|
||||
struct aibs_sensor *as;
|
||||
ACPI_INTEGER l, h;
|
||||
|
||||
switch (st) {
|
||||
case ENVSYS_STEMP:
|
||||
as = sc->sc_asens_temp;
|
||||
break;
|
||||
case ENVSYS_SFANRPM:
|
||||
as = sc->sc_asens_fan;
|
||||
break;
|
||||
case ENVSYS_SVOLTS_DC:
|
||||
as = sc->sc_asens_volt;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
if (as == NULL)
|
||||
return;
|
||||
for (i = 0; as[i].s.sensor != s->sensor; i++)
|
||||
;
|
||||
l = as[i].l;
|
||||
h = as[i].h;
|
||||
|
||||
switch (st) {
|
||||
case ENVSYS_STEMP:
|
||||
li->sel_critmax = h * 100 * 1000 + 273150000;
|
||||
li->sel_warnmax = l * 100 * 1000 + 273150000;
|
||||
*props = PROP_CRITMAX | PROP_WARNMAX;
|
||||
break;
|
||||
case ENVSYS_SFANRPM:
|
||||
/* some boards have strange limits for fans */
|
||||
if (l == 0) {
|
||||
li->sel_warnmin = h;
|
||||
*props = PROP_WARNMIN;
|
||||
} else {
|
||||
li->sel_warnmin = l;
|
||||
li->sel_warnmax = h;
|
||||
*props = PROP_WARNMIN | PROP_WARNMAX;
|
||||
}
|
||||
break;
|
||||
case ENVSYS_SVOLTS_DC:
|
||||
li->sel_critmin = l * 1000;
|
||||
li->sel_critmax = h * 1000;
|
||||
*props = PROP_CRITMIN | PROP_CRITMAX;
|
||||
break;
|
||||
default:
|
||||
/* NOTREACHED */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
MODULE(MODULE_CLASS_DRIVER, aibs, NULL);
|
||||
|
||||
#ifdef _MODULE
|
||||
#include "ioconf.c"
|
||||
#endif
|
||||
|
||||
static int
|
||||
aibs_modcmd(modcmd_t cmd, void *aux)
|
||||
{
|
||||
int rv = 0;
|
||||
|
||||
switch (cmd) {
|
||||
|
||||
case MODULE_CMD_INIT:
|
||||
|
||||
#ifdef _MODULE
|
||||
rv = config_init_component(cfdriver_ioconf_aibs,
|
||||
cfattach_ioconf_aibs, cfdata_ioconf_aibs);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case MODULE_CMD_FINI:
|
||||
|
||||
#ifdef _MODULE
|
||||
rv = config_fini_component(cfdriver_ioconf_aibs,
|
||||
cfattach_ioconf_aibs, cfdata_ioconf_aibs);
|
||||
#endif
|
||||
break;
|
||||
|
||||
default:
|
||||
rv = ENOTTY;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
# $NetBSD: files.acpi,v 1.88 2011/02/27 17:10:33 jruoho Exp $
|
||||
# $NetBSD: files.acpi,v 1.89 2011/06/12 07:25:43 jruoho Exp $
|
||||
|
||||
include "dev/acpi/acpica/files.acpica"
|
||||
|
||||
|
@ -180,10 +180,10 @@ file dev/acpi/dalb_acpi.c acpidalb
|
|||
attach wb at acpinodebus with wb_acpi
|
||||
file dev/acpi/wb_acpi.c wb_acpi
|
||||
|
||||
# ASUSTeK AI Booster ATK0110
|
||||
# ASUSTeK AI Booster
|
||||
device aibs: sysmon_envsys
|
||||
attach aibs at acpinodebus
|
||||
file dev/acpi/atk0110.c aibs
|
||||
file dev/acpi/aibs_acpi.c aibs
|
||||
|
||||
# ACPI SMBus controller
|
||||
device acpismbus: i2cbus
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# $NetBSD: Makefile,v 1.3 2011/02/16 08:08:14 jruoho Exp $
|
||||
# $NetBSD: Makefile,v 1.4 2011/06/12 07:25:43 jruoho Exp $
|
||||
|
||||
.include "../Makefile.inc"
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
|||
|
||||
KMOD= aibs
|
||||
IOCONF= aibs.ioconf
|
||||
SRCS= atk0110.c
|
||||
SRCS= aibs_acpi.c
|
||||
|
||||
WARNS= 4
|
||||
|
||||
|
|
Loading…
Reference in New Issue