diff options
author | iwasaki <iwasaki@FreeBSD.org> | 2001-11-01 16:34:07 +0000 |
---|---|---|
committer | iwasaki <iwasaki@FreeBSD.org> | 2001-11-01 16:34:07 +0000 |
commit | f1842a13d838c3a94044961bbf70910f54a49956 (patch) | |
tree | 386182cbb6b07e9a3fa20ca8415118c34d61ecae /sys/dev/acpica | |
parent | 9440591aaa9e7f2d8ef542a245eb93b2c2547844 (diff) | |
download | FreeBSD-src-f1842a13d838c3a94044961bbf70910f54a49956.zip FreeBSD-src-f1842a13d838c3a94044961bbf70910f54a49956.tar.gz |
Some fix for the recent apm module changes.
- Now that apm loadable module can inform its existence to other kernel
components (e.g. i386/isa/clock.c:startrtclock()'s TCS hack).
- Exchange priority of SI_SUB_CPU and SI_SUB_KLD for above purpose.
- Add simple arbitration mechanism for APM vs. ACPI. This prevents
the kernel enables both of them.
- Remove obsolete `#ifdef DEV_APM' related code.
- Add abstracted interface for Powermanagement operations. Public apm(4)
functions, such as apm_suspend(), should be replaced new interfaces.
Currently only power_pm_suspend (successor of apm_suspend) is implemented.
Reviewed by: peter, arch@ and audit@
Diffstat (limited to 'sys/dev/acpica')
-rw-r--r-- | sys/dev/acpica/acpi.c | 75 |
1 files changed, 74 insertions, 1 deletions
diff --git a/sys/dev/acpica/acpi.c b/sys/dev/acpica/acpi.c index f930e02..17987f0 100644 --- a/sys/dev/acpica/acpi.c +++ b/sys/dev/acpica/acpi.c @@ -42,6 +42,7 @@ #include <sys/reboot.h> #include <sys/sysctl.h> #include <sys/ctype.h> +#include <sys/power.h> #include <machine/clock.h> #include <machine/resource.h> @@ -126,6 +127,8 @@ static void acpi_system_eventhandler_sleep(void *arg, int state); static void acpi_system_eventhandler_wakeup(void *arg, int state); static int acpi_sleep_state_sysctl(SYSCTL_HANDLER_ARGS); +static int acpi_pm_func(u_long cmd, void *arg, ...); + static device_method_t acpi_methods[] = { /* Device interface */ DEVMETHOD(device_identify, acpi_identify), @@ -185,7 +188,9 @@ acpi_modevent(struct module *mod, int event, void *junk) return(EPERM); break; case MOD_UNLOAD: - return(EBUSY); + if (!cold && power_pm_get_type() == POWER_PM_TYPE_ACPI) + return(EBUSY); + break; default: break; } @@ -268,6 +273,13 @@ acpi_probe(device_t dev) int error; FUNCTION_TRACE(__func__); + + if (power_pm_get_type() != POWER_PM_TYPE_NONE && + power_pm_get_type() != POWER_PM_TYPE_ACPI) { + device_printf(dev, "Other PM system enabled.\n"); + return_VALUE(ENXIO); + } + ACPI_LOCK; if ((status = AcpiGetTableHeader(ACPI_TABLE_XSDT, 1, &th)) != AE_OK) { @@ -441,6 +453,9 @@ acpi_attach(device_t dev) goto out; } + /* Register ACPI again to pass the correct argument of pm_func. */ + power_pm_register(POWER_PM_TYPE_ACPI, acpi_pm_func, sc); + error = 0; out: @@ -1863,3 +1878,61 @@ acpi_set_debugging(void *junk) } SYSINIT(acpi_debugging, SI_SUB_TUNABLES, SI_ORDER_ANY, acpi_set_debugging, NULL); #endif + +static int +acpi_pm_func(u_long cmd, void *arg, ...) +{ + int state, acpi_state; + int error; + struct acpi_softc *sc; + va_list ap; + + error = 0; + switch (cmd) { + case POWER_CMD_SUSPEND: + sc = (struct acpi_softc *)arg; + if (sc == NULL) { + error = EINVAL; + goto out; + } + + va_start(ap, arg); + state = va_arg(ap, int); + va_end(ap); + + switch (state) { + case POWER_SLEEP_STATE_STANDBY: + acpi_state = sc->acpi_standby_sx; + break; + case POWER_SLEEP_STATE_SUSPEND: + acpi_state = sc->acpi_suspend_sx; + break; + case POWER_SLEEP_STATE_HIBERNATE: + acpi_state = ACPI_STATE_S4; + break; + default: + error = EINVAL; + goto out; + } + + acpi_SetSleepState(sc, acpi_state); + break; + + default: + error = EINVAL; + goto out; + } + +out: + return (error); +} + +static void +acpi_pm_register(void *arg) +{ + + power_pm_register(POWER_PM_TYPE_ACPI, acpi_pm_func, NULL); +} + +SYSINIT(power, SI_SUB_KLD, SI_ORDER_ANY, acpi_pm_register, 0); + |