summaryrefslogtreecommitdiffstats
path: root/sys/dev/acpica
diff options
context:
space:
mode:
authortakawata <takawata@FreeBSD.org>2000-12-22 14:41:55 +0000
committertakawata <takawata@FreeBSD.org>2000-12-22 14:41:55 +0000
commit8ccea54a6853e94f01fa419f0971916050be00c8 (patch)
tree582be48b355dd6fb7b07b5b58a54455db15aa632 /sys/dev/acpica
parent27bc62ade6bdc34211220f5a625c37163891e303 (diff)
downloadFreeBSD-src-8ccea54a6853e94f01fa419f0971916050be00c8.zip
FreeBSD-src-8ccea54a6853e94f01fa419f0971916050be00c8.tar.gz
Add ACPI AC adaptor and ACPI Control Method Battery.
And install notify handler for thermal zone .
Diffstat (limited to 'sys/dev/acpica')
-rw-r--r--sys/dev/acpica/acpi_acad.c138
-rw-r--r--sys/dev/acpica/acpi_cmbat.c275
-rw-r--r--sys/dev/acpica/acpi_thermal.c46
-rw-r--r--sys/dev/acpica/acpiio.h24
4 files changed, 480 insertions, 3 deletions
diff --git a/sys/dev/acpica/acpi_acad.c b/sys/dev/acpica/acpi_acad.c
new file mode 100644
index 0000000..12d254e
--- /dev/null
+++ b/sys/dev/acpica/acpi_acad.c
@@ -0,0 +1,138 @@
+/*-
+ * Copyright (c) 2000 Takanori Watanabe
+ * All rights reserved.
+ *
+ * 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 AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD$
+ */
+
+#include "opt_acpi.h"
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/bus.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <sys/rman.h>
+#include <sys/ioccom.h>
+#include <sys/malloc.h>
+#include <sys/conf.h>
+
+#include "acpi.h"
+#include <dev/acpica/acpivar.h>
+#include <dev/acpica/acpiio.h>
+
+
+#define ACPI_DEVICE_CHECK_PNP 0x00
+#define ACPI_DEVICE_CHECK_EXISTENCE 0x01
+#define ACPI_POWERSOURCE_STAT_CHANGE 0x80
+
+static void acpi_acad_get_status(void * );
+static void acpi_acad_notify_handler(ACPI_HANDLE , UINT32 ,void *);
+static int acpi_acad_probe(device_t);
+static int acpi_acad_attach(device_t);
+
+struct acpi_acad_softc {
+ int status;
+};
+
+static void
+acpi_acad_get_status(void *context)
+{
+ device_t dev = context;
+ struct acpi_acad_softc *sc = device_get_softc(dev);
+ ACPI_HANDLE h = acpi_get_handle(dev);
+
+ if (acpi_EvaluateNumber(h, "_PSR", &sc->status) != AE_OK)
+ return;
+ device_printf(dev,"%s\n",(sc->status) ? "On Line" : "Off Line");
+}
+
+static void
+acpi_acad_notify_handler(ACPI_HANDLE h, UINT32 notify, void *context)
+{
+ device_t dev = context;
+
+ device_printf(dev, "Notify %d\n", notify);
+ switch (notify) {
+ case ACPI_DEVICE_CHECK_PNP:
+ case ACPI_DEVICE_CHECK_EXISTENCE:
+ case ACPI_POWERSOURCE_STAT_CHANGE:
+ /*Temporally. It is better to notify policy manager*/
+ AcpiOsQueueForExecution(OSD_PRIORITY_LO,
+ acpi_acad_get_status,context);
+ break;
+ default:
+ break;
+ }
+}
+
+static int
+acpi_acad_probe(device_t dev)
+{
+
+ if ((acpi_get_type(dev) == ACPI_TYPE_DEVICE) &&
+ acpi_MatchHid(dev, "ACPI0003")) {
+
+ /*
+ * Set device description
+ */
+ device_set_desc(dev, "AC adapter");
+ return(0);
+ }
+ return(ENXIO);
+}
+
+static int
+acpi_acad_attach(device_t dev)
+{
+
+ ACPI_HANDLE handle = acpi_get_handle(dev);
+ AcpiInstallNotifyHandler(handle,
+ ACPI_DEVICE_NOTIFY,
+ acpi_acad_notify_handler, dev);
+ /*Installing system notify is not so good*/
+ AcpiInstallNotifyHandler(handle,
+ ACPI_SYSTEM_NOTIFY,
+ acpi_acad_notify_handler, dev);
+
+ acpi_acad_get_status((void *)dev);
+ return(0);
+}
+
+static device_method_t acpi_acad_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, acpi_acad_probe),
+ DEVMETHOD(device_attach, acpi_acad_attach),
+
+ {0, 0}
+};
+
+static driver_t acpi_acad_driver = {
+ "acpi_acad",
+ acpi_acad_methods,
+ sizeof(struct acpi_acad_softc),
+};
+
+static devclass_t acpi_acad_devclass;
+DRIVER_MODULE(acpi_acad,acpi,acpi_acad_driver,acpi_acad_devclass,0,0);
diff --git a/sys/dev/acpica/acpi_cmbat.c b/sys/dev/acpica/acpi_cmbat.c
new file mode 100644
index 0000000..03aed81
--- /dev/null
+++ b/sys/dev/acpica/acpi_cmbat.c
@@ -0,0 +1,275 @@
+/*-
+ * Copyright (c) 2000 Takanori Watanabe
+ * Copyright (c) 2000 Mitsuru IWASAKI <iwasaki@FreeBSD.org>
+ * All rights reserved.
+ *
+ * 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 AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD$
+ */
+
+#include "opt_acpi.h"
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/bus.h>
+#include <sys/ioccom.h>
+#include <sys/conf.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <sys/rman.h>
+#include <sys/malloc.h>
+
+#include "acpi.h"
+
+#include <dev/acpica/acpivar.h>
+#include <dev/acpica/acpiio.h>
+
+struct acpi_cmbat_softc {
+ device_t dev;
+ struct acpi_bif bif;
+ struct acpi_bst bst;
+ ACPI_BUFFER bif_buffer;
+ ACPI_BUFFER bst_buffer;
+};
+
+/* XXX: devclass_get_maxunit() don't give us the current allocated units... */
+static int acpi_cmbat_units = 0;
+
+#define ACPI_BATTERY_BST_CHANGE 0x80
+#define ACPI_BATTERY_BIF_CHANGE 0x81
+
+#define PKG_GETINT(res, tmp, idx, dest, label) do { \
+ tmp = &res->Package.Elements[idx]; \
+ if (tmp->Type != ACPI_TYPE_NUMBER) \
+ goto label ; \
+ dest = tmp->Number.Value; \
+} while(0)
+
+#define PKG_GETSTR(res, tmp, idx, dest, size, label) do { \
+ size_t length; \
+ length = size; \
+ tmp = &res->Package.Elements[idx]; \
+ bzero(dest, sizeof(dest)); \
+ switch (tmp->Type) { \
+ case ACPI_TYPE_STRING: \
+ if (tmp->String.Length < length) { \
+ length = tmp->String.Length; \
+ } \
+ strncpy(dest, tmp->String.Pointer, length); \
+ break; \
+ case ACPI_TYPE_BUFFER: \
+ if (tmp->Buffer.Length < length) { \
+ length = tmp->String.Length; \
+ } \
+ strncpy(dest, tmp->Buffer.Pointer, length); \
+ break; \
+ default: \
+ goto label; \
+ } \
+ dest[length-1] = '\0'; \
+} while(0)
+
+static void
+acpi_cmbat_get_bst(void *context)
+{
+ device_t dev = context;
+ struct acpi_cmbat_softc *sc = device_get_softc(dev);
+ ACPI_STATUS as;
+ ACPI_OBJECT *res, *tmp;
+ ACPI_HANDLE h = acpi_get_handle(dev);
+
+retry:
+ if (sc->bst_buffer.Length == 0) {
+ sc->bst_buffer.Pointer = NULL;
+ as = AcpiEvaluateObject(h, "_BST", NULL, &sc->bst_buffer);
+ if (as != AE_BUFFER_OVERFLOW){
+ device_printf(dev, "CANNOT FOUND _BST (%d)\n", as);
+ return;
+ }
+
+ sc->bst_buffer.Pointer = malloc(sc->bst_buffer.Length, M_DEVBUF, M_NOWAIT);
+ if (sc->bst_buffer.Pointer == NULL) {
+ device_printf(dev,"malloc failed");
+ return;
+ }
+ }
+
+ as = AcpiEvaluateObject(h, "_BST", NULL, &sc->bst_buffer);
+
+ if (as == AE_BUFFER_OVERFLOW){
+ if (sc->bst_buffer.Pointer){
+ free(sc->bst_buffer.Pointer, M_DEVBUF);
+ }
+ device_printf(dev, "bst size changed to %d\n", sc->bst_buffer.Length);
+ sc->bst_buffer.Length = 0;
+ goto retry;
+ } else if (as != AE_OK){
+ device_printf(dev, "CANNOT FOUND _BST (%d)\n", as);
+ return;
+ }
+
+ res = sc->bst_buffer.Pointer;
+
+ if ((res->Type != ACPI_TYPE_PACKAGE) && (res->Package.Count < 4))
+ return ;
+
+ PKG_GETINT(res, tmp, 0, sc->bst.state, end);
+ PKG_GETINT(res, tmp, 1, sc->bst.rate, end);
+ PKG_GETINT(res, tmp, 2, sc->bst.cap, end);
+ PKG_GETINT(res, tmp, 3, sc->bst.volt, end);
+end:
+}
+
+static void
+acpi_cmbat_get_bif(void *context)
+{
+ device_t dev = context;
+ struct acpi_cmbat_softc *sc = device_get_softc(dev);
+ ACPI_STATUS as;
+ ACPI_HANDLE h = acpi_get_handle(dev);
+ ACPI_OBJECT *res, *tmp;
+
+retry:
+ if (sc->bif_buffer.Length == 0) {
+ sc->bif_buffer.Pointer = NULL;
+ as = AcpiEvaluateObject(h, "_BST", NULL, &sc->bif_buffer);
+ if (as != AE_BUFFER_OVERFLOW){
+ device_printf(dev, "CANNOT FOUND _BST (%d)\n", as);
+ return;
+ }
+
+ sc->bif_buffer.Pointer = malloc(sc->bif_buffer.Length, M_DEVBUF, M_NOWAIT);
+ if (sc->bif_buffer.Pointer == NULL) {
+ device_printf(dev,"malloc failed");
+ return;
+ }
+ }
+
+ as = AcpiEvaluateObject(h, "_BST", NULL, &sc->bif_buffer);
+
+ if (as == AE_BUFFER_OVERFLOW){
+ if (sc->bif_buffer.Pointer){
+ free(sc->bif_buffer.Pointer, M_DEVBUF);
+ }
+ device_printf(dev, "bif size changed to %d\n", sc->bif_buffer.Length);
+ sc->bif_buffer.Length = 0;
+ goto retry;
+ } else if (as != AE_OK){
+ device_printf(dev, "CANNOT FOUND _BST (%d)\n", as);
+ return;
+ }
+
+ res = sc->bif_buffer.Pointer;
+ if ((res->Type != ACPI_TYPE_PACKAGE) && (res->Package.Count < 13))
+ return ;
+
+ PKG_GETINT(res, tmp, 0, sc->bif.unit, end);
+ PKG_GETINT(res, tmp, 1, sc->bif.dcap, end);
+ PKG_GETINT(res, tmp, 2, sc->bif.lfcap, end);
+ PKG_GETINT(res, tmp, 3, sc->bif.btech, end);
+ PKG_GETINT(res, tmp, 4, sc->bif.dvol, end);
+ PKG_GETINT(res, tmp, 5, sc->bif.wcap, end);
+ PKG_GETINT(res, tmp, 6, sc->bif.lcap, end);
+ PKG_GETINT(res, tmp, 7, sc->bif.gra1, end);
+ PKG_GETINT(res, tmp, 8, sc->bif.gra2, end);
+ PKG_GETSTR(res, tmp, 9, sc->bif.model, ACPI_CMBAT_MAXSTRLEN, end);
+ PKG_GETSTR(res, tmp, 10, sc->bif.serial, ACPI_CMBAT_MAXSTRLEN, end);
+ PKG_GETSTR(res, tmp, 11, sc->bif.type, ACPI_CMBAT_MAXSTRLEN, end);
+ PKG_GETSTR(res, tmp, 12, sc->bif.oeminfo, ACPI_CMBAT_MAXSTRLEN, end);
+end:
+}
+
+static void
+acpi_cmbat_notify_handler(ACPI_HANDLE h, UINT32 notify, void *context)
+{
+ switch (notify) {
+#if 0
+ /* XXX
+ * AML method execution is somewhat heavy even using swi.
+ * better to disable them until we fix the problem.
+ */
+ case ACPI_BATTERY_BST_CHANGE:
+ AcpiOsQueueForExecution(OSD_PRIORITY_LO,
+ acpi_cmbat_get_bst, context);
+ break;
+ case ACPI_BATTERY_BIF_CHANGE:
+ AcpiOsQueueForExecution(OSD_PRIORITY_LO,
+ acpi_cmbat_get_bif, context);
+ break;
+#endif
+ default:
+ break;
+ }
+}
+
+static int
+acpi_cmbat_probe(device_t dev)
+{
+
+ if ((acpi_get_type(dev) == ACPI_TYPE_DEVICE) &&
+ acpi_MatchHid(dev, "PNP0C0A")) {
+ /*
+ * Set device description
+ */
+ device_set_desc(dev, "Control method Battery");
+ return(0);
+ }
+ return(ENXIO);
+}
+
+static int
+acpi_cmbat_attach(device_t dev)
+{
+ ACPI_HANDLE handle = acpi_get_handle(dev);
+ struct acpi_cmbat_softc *sc;
+ sc = device_get_softc(dev);
+ AcpiInstallNotifyHandler(handle, ACPI_DEVICE_NOTIFY,
+ acpi_cmbat_notify_handler,dev);
+ bzero(&sc->bif_buffer, sizeof(sc->bif_buffer));
+ bzero(&sc->bst_buffer, sizeof(sc->bst_buffer));
+
+ acpi_cmbat_get_bif(dev);
+ acpi_cmbat_get_bst(dev);
+
+
+ acpi_cmbat_units++;
+
+ return(0);
+}
+
+static device_method_t acpi_cmbat_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, acpi_cmbat_probe),
+ DEVMETHOD(device_attach, acpi_cmbat_attach),
+
+ {0, 0}
+};
+
+static driver_t acpi_cmbat_driver = {
+ "acpi_cmbat",
+ acpi_cmbat_methods,
+ sizeof(struct acpi_cmbat_softc),
+};
+
+static devclass_t acpi_cmbat_devclass;
+DRIVER_MODULE(acpi_cmbat, acpi, acpi_cmbat_driver, acpi_cmbat_devclass, 0, 0);
diff --git a/sys/dev/acpica/acpi_thermal.c b/sys/dev/acpica/acpi_thermal.c
index 273729c..f7370dc 100644
--- a/sys/dev/acpica/acpi_thermal.c
+++ b/sys/dev/acpica/acpi_thermal.c
@@ -51,7 +51,7 @@ struct acpi_tz_softc {
static int acpi_tz_probe(device_t dev);
static int acpi_tz_attach(device_t dev);
-
+static void acpi_tz_check_tripping_point(void *context);
static device_method_t acpi_tz_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, acpi_tz_probe),
@@ -82,7 +82,38 @@ acpi_tz_probe(device_t dev)
}
return_VALUE(ENXIO);
}
-
+static void acpi_tz_check_tripping_point(void *context)
+{
+ device_t dev = context;
+ struct acpi_tz_softc *sc;
+ UINT32 param[4];
+ ACPI_BUFFER b;
+ sc = device_get_softc(dev);
+ b.Pointer = &param[0];
+ b.Length = sizeof(param);
+ if((AcpiEvaluateObject(sc->tz_handle,"_TMP",NULL,&b)) != AE_OK){
+ device_printf(dev,"CANNOT FOUND _TMP\n");
+ return;
+ }
+
+ device_printf(dev,"%d.%d K\n",param[1]/10,param[1]%10);
+ return;
+}
+#define ACPI_TZ_STATUS_CHANGE 0x80
+#define ACPI_TZ_TRIPPOINT_CHANGE 0x81
+static void acpi_tz_notify_handler( ACPI_HANDLE h,UINT32 notify, void *context)
+{
+ device_t dev = context;
+
+ switch(notify){
+ case ACPI_TZ_STATUS_CHANGE:
+ case ACPI_TZ_TRIPPOINT_CHANGE:
+ /*Check trip point*/
+ AcpiOsQueueForExecution(OSD_PRIORITY_LO,
+ acpi_tz_check_tripping_point,context);
+ break;
+ }
+}
static int
acpi_tz_attach(device_t dev)
{
@@ -109,6 +140,15 @@ acpi_tz_attach(device_t dev)
return_VALUE(ENXIO);
}
device_printf(sc->tz_dev, "current temperature %d.%dC\n", TZ_KELVTOC(param[1]));
-
+
+ AcpiInstallNotifyHandler(sc->tz_handle,ACPI_DEVICE_NOTIFY,
+ acpi_tz_notify_handler,dev);
return_VALUE(0);
}
+
+
+
+
+
+
+
diff --git a/sys/dev/acpica/acpiio.h b/sys/dev/acpica/acpiio.h
index 2e1fb12..fec9dc2 100644
--- a/sys/dev/acpica/acpiio.h
+++ b/sys/dev/acpica/acpiio.h
@@ -34,6 +34,30 @@
#define ACPIIO_DISABLE _IO('P', 2)
#define ACPIIO_SETSLPSTATE _IOW('P', 3, int)
+#define ACPI_CMBAT_MAXSTRLEN 32
+struct acpi_bif {
+ u_int32_t unit; /* 0 for mWh, 1 for mAh */
+ u_int32_t dcap; /* Design Capacity */
+ u_int32_t btech; /* Battery Technorogy */
+ u_int32_t lfcap; /* Last Full capacity */
+ u_int32_t dvol; /* Design voltage (mV) */
+ u_int32_t wcap; /* WARN capacity */
+ u_int32_t lcap; /* Low capacity */
+ u_int32_t gra1; /* Granulity 1(Warn to Low) */
+ u_int32_t gra2; /* Granulity 2(Full to Warn) */
+ char model[ACPI_CMBAT_MAXSTRLEN]; /* model identifier */
+ char serial[ACPI_CMBAT_MAXSTRLEN]; /* Serial number */
+ char type[ACPI_CMBAT_MAXSTRLEN]; /* Type */
+ char oeminfo[ACPI_CMBAT_MAXSTRLEN]; /* OEM infomation */
+};
+
+struct acpi_bst {
+ u_int32_t state; /* Battery State */
+ u_int32_t rate; /* Present Rate */
+ u_int32_t cap; /* Remaining Capacity */
+ u_int32_t volt; /* Present Voltage */
+};
+
#ifdef _KERNEL
extern int acpi_register_ioctl(u_long cmd, int (* fn)(u_long cmd, caddr_t addr, void *arg), void *arg);
extern void acpi_deregister_ioctl(u_long cmd, int (* fn)(u_long cmd, caddr_t addr, void *arg));
OpenPOWER on IntegriCloud