summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoriwasaki <iwasaki@FreeBSD.org>2001-10-26 17:43:05 +0000
committeriwasaki <iwasaki@FreeBSD.org>2001-10-26 17:43:05 +0000
commit1b24a8aa4e560f424c368bcc1fa8037f4773cea2 (patch)
tree21b123760e3f3009d3682b32acb590e02ad68027
parent5cf7b5f41f4236d42751f1ffbb7c54d5160772ca (diff)
downloadFreeBSD-src-1b24a8aa4e560f424c368bcc1fa8037f4773cea2.zip
FreeBSD-src-1b24a8aa4e560f424c368bcc1fa8037f4773cea2.tar.gz
Add APM compatibility feature to ACPI.
This emulates APM device node interface APIs (mainly ioctl) and provides APM services for the applications. The goal is to support most of APM applications without any changes. Implemented ioctls in this commit are: - APMIO_SUSPEND (mapped ACPI S3 as default but changable by sysctl) - APMIO_STANDBY (mapped ACPI S1 as default but changable by sysctl) - APMIO_GETINFO and APMIO_GETINFO_OLD - APMIO_GETPWSTATUS With above, many APM applications which get batteries, ac-line info. and transition the system into suspend/standby mode (such as wmapm, xbatt) should work with ACPI enabled kernel (if ACPI works well :-) Reviewed by: arch@, audit@ and some guys
-rw-r--r--sys/amd64/acpica/acpi_machdep.c335
-rw-r--r--sys/conf/files.i3861
-rw-r--r--sys/conf/files.ia641
-rw-r--r--sys/dev/acpica/acpi.c15
-rw-r--r--sys/dev/acpica/acpi_acad.c27
-rw-r--r--sys/dev/acpica/acpi_battery.c6
-rw-r--r--sys/dev/acpica/acpivar.h15
-rw-r--r--sys/i386/acpica/acpi_machdep.c335
-rw-r--r--sys/ia64/acpica/acpi_machdep.c48
-rw-r--r--sys/modules/acpi/Makefile4
10 files changed, 776 insertions, 11 deletions
diff --git a/sys/amd64/acpica/acpi_machdep.c b/sys/amd64/acpica/acpi_machdep.c
new file mode 100644
index 0000000..228c4b7
--- /dev/null
+++ b/sys/amd64/acpica/acpi_machdep.c
@@ -0,0 +1,335 @@
+/*-
+ * Copyright (c) 2001 Mitsuru IWASAKI
+ * 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 <sys/param.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/fcntl.h>
+#include <sys/uio.h>
+
+#include "acpi.h"
+
+#include <dev/acpica/acpivar.h>
+#include <dev/acpica/acpiio.h>
+
+static device_t acpi_dev;
+
+/*
+ * APM driver emulation
+ */
+
+#include <sys/selinfo.h>
+
+#include <machine/apm_bios.h>
+#include <machine/pc/bios.h>
+
+#include <i386/apm/apm.h>
+
+static struct apm_softc apm_softc;
+
+static d_open_t apmopen;
+static d_close_t apmclose;
+static d_write_t apmwrite;
+static d_ioctl_t apmioctl;
+static d_poll_t apmpoll;
+
+#define CDEV_MAJOR 39
+static struct cdevsw apm_cdevsw = {
+ /* open */ apmopen,
+ /* close */ apmclose,
+ /* read */ noread,
+ /* write */ apmwrite,
+ /* ioctl */ apmioctl,
+ /* poll */ apmpoll,
+ /* mmap */ nommap,
+ /* strategy */ nostrategy,
+ /* name */ "apm",
+ /* maj */ CDEV_MAJOR,
+ /* dump */ nodump,
+ /* psize */ nopsize,
+ /* flags */ 0,
+};
+
+static int
+acpi_capm_convert_battstate(struct acpi_battinfo *battp)
+{
+ int state;
+
+ state = 0xff; /* XXX unknown */
+
+ if (battp->state & ACPI_BATT_STAT_DISCHARG) {
+ if (battp->cap >= 50) {
+ state = 0; /* high */
+ } else {
+ state = 1; /* low */
+ }
+ }
+ if (battp->state & ACPI_BATT_STAT_CRITICAL) {
+ state = 2; /* critical */
+ }
+ if (battp->state & ACPI_BATT_STAT_CHARGING) {
+ state = 3; /* charging */
+ }
+ return (state);
+}
+
+static int
+acpi_capm_convert_battflags(struct acpi_battinfo *battp)
+{
+ int flags;
+
+ flags = 0;
+
+ if (battp->cap >= 50) {
+ flags |= APM_BATT_HIGH;
+ } else {
+ if (battp->state & ACPI_BATT_STAT_CRITICAL) {
+ flags |= APM_BATT_CRITICAL;
+ } else {
+ flags |= APM_BATT_LOW;
+ }
+ }
+ if (battp->state & ACPI_BATT_STAT_CHARGING) {
+ flags |= APM_BATT_CHARGING;
+ }
+ if (battp->state == ACPI_BATT_STAT_NOT_PRESENT) {
+ flags = APM_BATT_NOT_PRESENT;
+ }
+
+ return (flags);
+}
+
+static int
+acpi_capm_get_info(apm_info_t aip)
+{
+ int acline;
+ struct acpi_battinfo batt;
+
+ aip->ai_infoversion = 1;
+ aip->ai_major = 1;
+ aip->ai_minor = 2;
+ aip->ai_status = apm_softc.active;
+ aip->ai_capabilities= 0xff00; /* XXX unknown */
+
+ if (acpi_acad_get_acline(&acline)) {
+ aip->ai_acline = 0xff; /* unknown */
+ } else {
+ aip->ai_acline = acline; /* on/off */
+ }
+
+ if (acpi_battery_get_battinfo(-1, &batt)) {
+ aip->ai_batt_stat = 0xff; /* unknown */
+ aip->ai_batt_life = 0xff; /* unknown */
+ aip->ai_batt_time = -1; /* unknown */
+ aip->ai_batteries = 0;
+ } else {
+ aip->ai_batt_stat = acpi_capm_convert_battstate(&batt);
+ aip->ai_batt_life = batt.cap;
+ aip->ai_batt_time = (batt.min == -1) ? -1 : batt.min * 60;
+ aip->ai_batteries = acpi_battery_get_units();
+ }
+
+ return (0);
+}
+
+static int
+acpi_capm_get_pwstatus(apm_pwstatus_t app)
+{
+ int batt_unit;
+ int acline;
+ struct acpi_battinfo batt;
+
+ if (app->ap_device != PMDV_ALLDEV &&
+ (app->ap_device < PMDV_BATT0 || app->ap_device > PMDV_BATT_ALL)) {
+ return (1);
+ }
+
+ if (app->ap_device == PMDV_ALLDEV) {
+ batt_unit = -1; /* all units */
+ } else {
+ batt_unit = app->ap_device - PMDV_BATT0;
+ }
+
+ if (acpi_battery_get_battinfo(batt_unit, &batt)) {
+ return (1);
+ }
+
+ app->ap_batt_stat = acpi_capm_convert_battstate(&batt);
+ app->ap_batt_flag = acpi_capm_convert_battflags(&batt);
+ app->ap_batt_life = batt.cap;
+ app->ap_batt_time = (batt.min == -1) ? -1 : batt.min * 60;
+
+ if (acpi_acad_get_acline(&acline)) {
+ app->ap_acline = 0xff; /* unknown */
+ } else {
+ app->ap_acline = acline; /* on/off */
+ }
+
+ return (0);
+}
+
+static int
+apmopen(dev_t dev, int flag, int fmt, struct thread *td)
+{
+ return (0);
+}
+
+static int
+apmclose(dev_t dev, int flag, int fmt, struct thread *td)
+{
+ return (0);
+}
+
+static int
+apmioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct thread *td)
+{
+ int error = 0;
+ struct acpi_softc *acpi_sc;
+ struct apm_info info;
+ apm_info_old_t aiop;
+
+ if ((acpi_sc = device_get_softc(acpi_dev)) == NULL) {
+ return (ENXIO);
+ }
+
+ switch (cmd) {
+ case APMIO_SUSPEND:
+ if (!(flag & FWRITE))
+ return (EPERM);
+ if (apm_softc.active)
+ acpi_SetSleepState(acpi_sc, acpi_sc->acpi_suspend_sx);
+ else
+ error = EINVAL;
+ break;
+
+ case APMIO_STANDBY:
+ if (!(flag & FWRITE))
+ return (EPERM);
+ if (apm_softc.active)
+ acpi_SetSleepState(acpi_sc, acpi_sc->acpi_standby_sx);
+ else
+ error = EINVAL;
+ break;
+
+ case APMIO_GETINFO_OLD:
+ if (acpi_capm_get_info(&info))
+ error = ENXIO;
+ aiop = (apm_info_old_t)addr;
+ aiop->ai_major = info.ai_major;
+ aiop->ai_minor = info.ai_minor;
+ aiop->ai_acline = info.ai_acline;
+ aiop->ai_batt_stat = info.ai_batt_stat;
+ aiop->ai_batt_life = info.ai_batt_life;
+ aiop->ai_status = info.ai_status;
+ break;
+
+ case APMIO_GETINFO:
+ if (acpi_capm_get_info((apm_info_t)addr))
+ error = ENXIO;
+
+ break;
+
+ case APMIO_GETPWSTATUS:
+ if (acpi_capm_get_pwstatus((apm_pwstatus_t)addr))
+ error = ENXIO;
+ break;
+
+ case APMIO_ENABLE:
+ if (!(flag & FWRITE))
+ return (EPERM);
+ apm_softc.active = 1;
+ break;
+
+ case APMIO_DISABLE:
+ if (!(flag & FWRITE))
+ return (EPERM);
+ apm_softc.active = 0;
+ break;
+
+ case APMIO_HALTCPU:
+ break;
+
+ case APMIO_NOTHALTCPU:
+ break;
+
+ case APMIO_DISPLAY:
+ if (!(flag & FWRITE))
+ return (EPERM);
+ break;
+
+ case APMIO_BIOS:
+ if (!(flag & FWRITE))
+ return (EPERM);
+ bzero(addr, sizeof(struct apm_bios_arg));
+ break;
+
+ default:
+ error = EINVAL;
+ break;
+ }
+
+ return (error);
+}
+
+static int
+apmwrite(dev_t dev, struct uio *uio, int ioflag)
+{
+
+ return (uio->uio_resid);
+}
+
+static int
+apmpoll(dev_t dev, int events, struct thread *td)
+{
+ return (0);
+}
+
+static void
+acpi_capm_init(struct acpi_softc *sc)
+{
+
+ make_dev(&apm_cdevsw, 0, 0, 5, 0664, "apm");
+}
+
+int
+acpi_machdep_init(device_t dev)
+{
+ struct acpi_softc *sc;
+
+ acpi_dev = dev;
+ if ((sc = device_get_softc(acpi_dev)) == NULL) {
+ return (ENXIO);
+ }
+
+ acpi_capm_init(sc);
+
+ acpi_install_wakeup_handler(sc);
+
+ return (0);
+}
+
diff --git a/sys/conf/files.i386 b/sys/conf/files.i386
index 3888aa5..a53e705 100644
--- a/sys/conf/files.i386
+++ b/sys/conf/files.i386
@@ -168,6 +168,7 @@ gnu/i386/fpemul/reg_u_sub.s optional gpl_math_emulate
gnu/i386/fpemul/wm_shrx.s optional gpl_math_emulate
gnu/i386/fpemul/wm_sqrt.s optional gpl_math_emulate
i386/acpica/OsdEnvironment.c optional acpica
+i386/acpica/acpi_machdep.c optional acpica
i386/acpica/acpi_wakeup.c optional acpica
acpi_wakecode.h optional acpica \
dependency "$S/i386/acpica/acpi_wakecode.S" \
diff --git a/sys/conf/files.ia64 b/sys/conf/files.ia64
index 9b99b69..e537bb3 100644
--- a/sys/conf/files.ia64
+++ b/sys/conf/files.ia64
@@ -18,6 +18,7 @@ atkbdmap.h optional atkbd_dflt_keymap \
no-obj no-implicit-rule before-depend \
clean "atkbdmap.h"
#
+ia64/acpica/acpi_machdep.c optional acpica
ia64/acpica/acpi_wakeup.c optional acpica
ia64/acpica/OsdEnvironment.c optional acpica
ia64/acpica/madt.c optional acpica
diff --git a/sys/dev/acpica/acpi.c b/sys/dev/acpica/acpi.c
index 3522f23..60e20f9 100644
--- a/sys/dev/acpica/acpi.c
+++ b/sys/dev/acpica/acpi.c
@@ -300,8 +300,6 @@ acpi_attach(device_t dev)
bzero(sc, sizeof(*sc));
sc->acpi_dev = dev;
- acpi_install_wakeup_handler(sc);
-
#ifdef ENABLE_DEBUGGER
if (debugpoint && !strcmp(debugpoint, "spaces"))
acpi_EnterDebugger();
@@ -375,6 +373,12 @@ acpi_attach(device_t dev)
SYSCTL_ADD_PROC(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree),
OID_AUTO, "lid_switch_state", CTLTYPE_STRING | CTLFLAG_RW,
&sc->acpi_lid_switch_sx, 0, acpi_sleep_state_sysctl, "A", "");
+ SYSCTL_ADD_PROC(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree),
+ OID_AUTO, "standby_state", CTLTYPE_STRING | CTLFLAG_RW,
+ &sc->acpi_standby_sx, 0, acpi_sleep_state_sysctl, "A", "");
+ SYSCTL_ADD_PROC(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree),
+ OID_AUTO, "suspend_state", CTLTYPE_STRING | CTLFLAG_RW,
+ &sc->acpi_suspend_sx, 0, acpi_sleep_state_sysctl, "A", "");
/*
* Dispatch the default sleep state to devices.
@@ -383,6 +387,8 @@ acpi_attach(device_t dev)
sc->acpi_power_button_sx = ACPI_POWER_BUTTON_DEFAULT_SX;
sc->acpi_sleep_button_sx = ACPI_SLEEP_BUTTON_DEFAULT_SX;
sc->acpi_lid_switch_sx = ACPI_LID_SWITCH_DEFAULT_SX;
+ sc->acpi_standby_sx = ACPI_STATE_S1;
+ sc->acpi_suspend_sx = ACPI_STATE_S3;
acpi_enable_fixed_events(sc);
@@ -425,6 +431,11 @@ acpi_attach(device_t dev)
if (debugpoint && !strcmp(debugpoint, "running"))
acpi_EnterDebugger();
#endif
+
+ if ((error = acpi_machdep_init(dev))) {
+ goto out;
+ }
+
error = 0;
out:
diff --git a/sys/dev/acpica/acpi_acad.c b/sys/dev/acpica/acpi_acad.c
index a20d3ee..5b4f751 100644
--- a/sys/dev/acpica/acpi_acad.c
+++ b/sys/dev/acpica/acpi_acad.c
@@ -207,18 +207,37 @@ acpi_acad_sysctl(SYSCTL_HANDLER_ARGS)
{
int val;
int error;
- device_t dev;
+
+ if (acpi_acad_get_acline(&val)) {
+ return (ENXIO);
+ }
+
+ val = *(u_int *)oidp->oid_arg1;
+ error = sysctl_handle_int(oidp, &val, 0, req);
+ return (error);
+}
+
+/*
+ * Public interfaces.
+ */
+
+int
+acpi_acad_get_acline(int *status)
+{
+ device_t dev;
struct acpi_acad_softc *sc;
if ((dev = devclass_get_device(acpi_acad_devclass, 0)) == NULL) {
return (ENXIO);
}
+
if ((sc = device_get_softc(dev)) == NULL) {
return (ENXIO);
}
+
acpi_acad_get_status(dev);
- val = *(u_int *)oidp->oid_arg1;
- error = sysctl_handle_int(oidp, &val, 0, req);
- return (error);
+ *status = sc->status;
+
+ return (0);
}
diff --git a/sys/dev/acpica/acpi_battery.c b/sys/dev/acpica/acpi_battery.c
index 9b59293..ac6134a 100644
--- a/sys/dev/acpica/acpi_battery.c
+++ b/sys/dev/acpica/acpi_battery.c
@@ -65,14 +65,14 @@ static int acpi_batteries_initted = 0;
static int acpi_batteries_units = 0;
static struct acpi_battinfo acpi_battery_battinfo;
-static int
+int
acpi_battery_get_units(void)
{
return (acpi_batteries_units);
}
-static int
+int
acpi_battery_get_battdesc(int logical_unit, struct acpi_battdesc *battdesc)
{
int i;
@@ -95,7 +95,7 @@ acpi_battery_get_battdesc(int logical_unit, struct acpi_battdesc *battdesc)
return (ENXIO);
}
-static int
+int
acpi_battery_get_battinfo(int unit, struct acpi_battinfo *battinfo)
{
int error;
diff --git a/sys/dev/acpica/acpivar.h b/sys/dev/acpica/acpivar.h
index 566afc4..2fc0f89 100644
--- a/sys/dev/acpica/acpivar.h
+++ b/sys/dev/acpica/acpivar.h
@@ -57,6 +57,9 @@ struct acpi_softc {
int acpi_sleep_button_sx;
int acpi_lid_switch_sx;
+ int acpi_standby_sx;
+ int acpi_suspend_sx;
+
bus_dma_tag_t acpi_waketag;
bus_dmamap_t acpi_wakemap;
vm_offset_t acpi_wakeaddr;
@@ -303,6 +306,7 @@ extern char *acpi_name(ACPI_HANDLE handle);
extern int acpi_avoid(ACPI_HANDLE handle);
extern int acpi_disabled(char *subsys);
+extern int acpi_machdep_init(device_t dev);
extern void acpi_install_wakeup_handler(struct acpi_softc *sc);
extern int acpi_sleep_machdep(struct acpi_softc *sc, int state);
@@ -310,11 +314,22 @@ extern int acpi_sleep_machdep(struct acpi_softc *sc, int state);
* Battery Abstruction.
*/
struct acpi_battinfo;
+struct acpi_battdesc;
extern int acpi_battery_register(int, int);
+extern int acpi_battery_get_battinfo(int, struct acpi_battinfo *);
+extern int acpi_battery_get_units(void);
+extern int acpi_battery_get_battdesc(int, struct acpi_battdesc *);
+
extern int acpi_cmbat_get_battinfo(int, struct acpi_battinfo *);
/*
+ * AC adapter interface.
+ */
+
+extern int acpi_acad_get_acline(int *);
+
+/*
* System power API.
*
* XXX should this be further generalised?
diff --git a/sys/i386/acpica/acpi_machdep.c b/sys/i386/acpica/acpi_machdep.c
new file mode 100644
index 0000000..228c4b7
--- /dev/null
+++ b/sys/i386/acpica/acpi_machdep.c
@@ -0,0 +1,335 @@
+/*-
+ * Copyright (c) 2001 Mitsuru IWASAKI
+ * 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 <sys/param.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/fcntl.h>
+#include <sys/uio.h>
+
+#include "acpi.h"
+
+#include <dev/acpica/acpivar.h>
+#include <dev/acpica/acpiio.h>
+
+static device_t acpi_dev;
+
+/*
+ * APM driver emulation
+ */
+
+#include <sys/selinfo.h>
+
+#include <machine/apm_bios.h>
+#include <machine/pc/bios.h>
+
+#include <i386/apm/apm.h>
+
+static struct apm_softc apm_softc;
+
+static d_open_t apmopen;
+static d_close_t apmclose;
+static d_write_t apmwrite;
+static d_ioctl_t apmioctl;
+static d_poll_t apmpoll;
+
+#define CDEV_MAJOR 39
+static struct cdevsw apm_cdevsw = {
+ /* open */ apmopen,
+ /* close */ apmclose,
+ /* read */ noread,
+ /* write */ apmwrite,
+ /* ioctl */ apmioctl,
+ /* poll */ apmpoll,
+ /* mmap */ nommap,
+ /* strategy */ nostrategy,
+ /* name */ "apm",
+ /* maj */ CDEV_MAJOR,
+ /* dump */ nodump,
+ /* psize */ nopsize,
+ /* flags */ 0,
+};
+
+static int
+acpi_capm_convert_battstate(struct acpi_battinfo *battp)
+{
+ int state;
+
+ state = 0xff; /* XXX unknown */
+
+ if (battp->state & ACPI_BATT_STAT_DISCHARG) {
+ if (battp->cap >= 50) {
+ state = 0; /* high */
+ } else {
+ state = 1; /* low */
+ }
+ }
+ if (battp->state & ACPI_BATT_STAT_CRITICAL) {
+ state = 2; /* critical */
+ }
+ if (battp->state & ACPI_BATT_STAT_CHARGING) {
+ state = 3; /* charging */
+ }
+ return (state);
+}
+
+static int
+acpi_capm_convert_battflags(struct acpi_battinfo *battp)
+{
+ int flags;
+
+ flags = 0;
+
+ if (battp->cap >= 50) {
+ flags |= APM_BATT_HIGH;
+ } else {
+ if (battp->state & ACPI_BATT_STAT_CRITICAL) {
+ flags |= APM_BATT_CRITICAL;
+ } else {
+ flags |= APM_BATT_LOW;
+ }
+ }
+ if (battp->state & ACPI_BATT_STAT_CHARGING) {
+ flags |= APM_BATT_CHARGING;
+ }
+ if (battp->state == ACPI_BATT_STAT_NOT_PRESENT) {
+ flags = APM_BATT_NOT_PRESENT;
+ }
+
+ return (flags);
+}
+
+static int
+acpi_capm_get_info(apm_info_t aip)
+{
+ int acline;
+ struct acpi_battinfo batt;
+
+ aip->ai_infoversion = 1;
+ aip->ai_major = 1;
+ aip->ai_minor = 2;
+ aip->ai_status = apm_softc.active;
+ aip->ai_capabilities= 0xff00; /* XXX unknown */
+
+ if (acpi_acad_get_acline(&acline)) {
+ aip->ai_acline = 0xff; /* unknown */
+ } else {
+ aip->ai_acline = acline; /* on/off */
+ }
+
+ if (acpi_battery_get_battinfo(-1, &batt)) {
+ aip->ai_batt_stat = 0xff; /* unknown */
+ aip->ai_batt_life = 0xff; /* unknown */
+ aip->ai_batt_time = -1; /* unknown */
+ aip->ai_batteries = 0;
+ } else {
+ aip->ai_batt_stat = acpi_capm_convert_battstate(&batt);
+ aip->ai_batt_life = batt.cap;
+ aip->ai_batt_time = (batt.min == -1) ? -1 : batt.min * 60;
+ aip->ai_batteries = acpi_battery_get_units();
+ }
+
+ return (0);
+}
+
+static int
+acpi_capm_get_pwstatus(apm_pwstatus_t app)
+{
+ int batt_unit;
+ int acline;
+ struct acpi_battinfo batt;
+
+ if (app->ap_device != PMDV_ALLDEV &&
+ (app->ap_device < PMDV_BATT0 || app->ap_device > PMDV_BATT_ALL)) {
+ return (1);
+ }
+
+ if (app->ap_device == PMDV_ALLDEV) {
+ batt_unit = -1; /* all units */
+ } else {
+ batt_unit = app->ap_device - PMDV_BATT0;
+ }
+
+ if (acpi_battery_get_battinfo(batt_unit, &batt)) {
+ return (1);
+ }
+
+ app->ap_batt_stat = acpi_capm_convert_battstate(&batt);
+ app->ap_batt_flag = acpi_capm_convert_battflags(&batt);
+ app->ap_batt_life = batt.cap;
+ app->ap_batt_time = (batt.min == -1) ? -1 : batt.min * 60;
+
+ if (acpi_acad_get_acline(&acline)) {
+ app->ap_acline = 0xff; /* unknown */
+ } else {
+ app->ap_acline = acline; /* on/off */
+ }
+
+ return (0);
+}
+
+static int
+apmopen(dev_t dev, int flag, int fmt, struct thread *td)
+{
+ return (0);
+}
+
+static int
+apmclose(dev_t dev, int flag, int fmt, struct thread *td)
+{
+ return (0);
+}
+
+static int
+apmioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct thread *td)
+{
+ int error = 0;
+ struct acpi_softc *acpi_sc;
+ struct apm_info info;
+ apm_info_old_t aiop;
+
+ if ((acpi_sc = device_get_softc(acpi_dev)) == NULL) {
+ return (ENXIO);
+ }
+
+ switch (cmd) {
+ case APMIO_SUSPEND:
+ if (!(flag & FWRITE))
+ return (EPERM);
+ if (apm_softc.active)
+ acpi_SetSleepState(acpi_sc, acpi_sc->acpi_suspend_sx);
+ else
+ error = EINVAL;
+ break;
+
+ case APMIO_STANDBY:
+ if (!(flag & FWRITE))
+ return (EPERM);
+ if (apm_softc.active)
+ acpi_SetSleepState(acpi_sc, acpi_sc->acpi_standby_sx);
+ else
+ error = EINVAL;
+ break;
+
+ case APMIO_GETINFO_OLD:
+ if (acpi_capm_get_info(&info))
+ error = ENXIO;
+ aiop = (apm_info_old_t)addr;
+ aiop->ai_major = info.ai_major;
+ aiop->ai_minor = info.ai_minor;
+ aiop->ai_acline = info.ai_acline;
+ aiop->ai_batt_stat = info.ai_batt_stat;
+ aiop->ai_batt_life = info.ai_batt_life;
+ aiop->ai_status = info.ai_status;
+ break;
+
+ case APMIO_GETINFO:
+ if (acpi_capm_get_info((apm_info_t)addr))
+ error = ENXIO;
+
+ break;
+
+ case APMIO_GETPWSTATUS:
+ if (acpi_capm_get_pwstatus((apm_pwstatus_t)addr))
+ error = ENXIO;
+ break;
+
+ case APMIO_ENABLE:
+ if (!(flag & FWRITE))
+ return (EPERM);
+ apm_softc.active = 1;
+ break;
+
+ case APMIO_DISABLE:
+ if (!(flag & FWRITE))
+ return (EPERM);
+ apm_softc.active = 0;
+ break;
+
+ case APMIO_HALTCPU:
+ break;
+
+ case APMIO_NOTHALTCPU:
+ break;
+
+ case APMIO_DISPLAY:
+ if (!(flag & FWRITE))
+ return (EPERM);
+ break;
+
+ case APMIO_BIOS:
+ if (!(flag & FWRITE))
+ return (EPERM);
+ bzero(addr, sizeof(struct apm_bios_arg));
+ break;
+
+ default:
+ error = EINVAL;
+ break;
+ }
+
+ return (error);
+}
+
+static int
+apmwrite(dev_t dev, struct uio *uio, int ioflag)
+{
+
+ return (uio->uio_resid);
+}
+
+static int
+apmpoll(dev_t dev, int events, struct thread *td)
+{
+ return (0);
+}
+
+static void
+acpi_capm_init(struct acpi_softc *sc)
+{
+
+ make_dev(&apm_cdevsw, 0, 0, 5, 0664, "apm");
+}
+
+int
+acpi_machdep_init(device_t dev)
+{
+ struct acpi_softc *sc;
+
+ acpi_dev = dev;
+ if ((sc = device_get_softc(acpi_dev)) == NULL) {
+ return (ENXIO);
+ }
+
+ acpi_capm_init(sc);
+
+ acpi_install_wakeup_handler(sc);
+
+ return (0);
+}
+
diff --git a/sys/ia64/acpica/acpi_machdep.c b/sys/ia64/acpica/acpi_machdep.c
new file mode 100644
index 0000000..499a620
--- /dev/null
+++ b/sys/ia64/acpica/acpi_machdep.c
@@ -0,0 +1,48 @@
+/*-
+ * Copyright (c) 2001 Doug Rabson
+ * 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 <sys/param.h>
+#include <sys/bus.h>
+
+#include "acpi.h"
+#include <dev/acpica/acpivar.h>
+
+int
+acpi_machdep_init(device_t dev)
+{
+ struct acpi_softc *sc;
+
+ if ((sc = device_get_softc(dev)) == NULL) {
+ return (ENXIO);
+ }
+
+ acpi_install_wakeup_handler(sc);
+
+ return (0);
+}
+
diff --git a/sys/modules/acpi/Makefile b/sys/modules/acpi/Makefile
index 23a291d..aefef24 100644
--- a/sys/modules/acpi/Makefile
+++ b/sys/modules/acpi/Makefile
@@ -47,8 +47,8 @@ opt_ddb.h: Makefile
echo '' >opt_ddb.h
.endif
-# Machine-specific sleep/wakeup code
-SRCS+= acpi_wakecode.h acpi_wakeup.c
+# Machine-specific code such as sleep/wakeup
+SRCS+= acpi_machdep.c acpi_wakecode.h acpi_wakeup.c
CLEANFILES+= acpi_wakecode.h acpi_wakecode.o acpi_wakecode.bin
acpi_wakecode.h: acpi_wakecode.S
OpenPOWER on IntegriCloud