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 | |
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')
-rw-r--r-- | sys/amd64/amd64/tsc.c | 11 | ||||
-rw-r--r-- | sys/amd64/isa/clock.c | 11 | ||||
-rw-r--r-- | sys/conf/files | 1 | ||||
-rw-r--r-- | sys/dev/acpica/acpi.c | 75 | ||||
-rw-r--r-- | sys/dev/syscons/syscons.c | 14 | ||||
-rw-r--r-- | sys/i386/apm/apm.c | 98 | ||||
-rw-r--r-- | sys/i386/bios/apm.c | 98 | ||||
-rw-r--r-- | sys/i386/i386/tsc.c | 11 | ||||
-rw-r--r-- | sys/i386/isa/clock.c | 11 | ||||
-rw-r--r-- | sys/isa/atrtc.c | 11 | ||||
-rw-r--r-- | sys/kern/subr_power.c | 76 | ||||
-rw-r--r-- | sys/sys/kernel.h | 4 | ||||
-rw-r--r-- | sys/sys/power.h | 51 |
13 files changed, 419 insertions, 53 deletions
diff --git a/sys/amd64/amd64/tsc.c b/sys/amd64/amd64/tsc.c index 13e11a4..a7aaea0 100644 --- a/sys/amd64/amd64/tsc.c +++ b/sys/amd64/amd64/tsc.c @@ -49,7 +49,6 @@ */ #include "opt_clock.h" -#include "opt_apm.h" #include "opt_mca.h" #include <sys/param.h> @@ -63,6 +62,7 @@ #include <sys/kernel.h> #include <sys/sysctl.h> #include <sys/cons.h> +#include <sys/power.h> #include <machine/clock.h> #ifdef CLK_CALIBRATION_LOOP @@ -823,7 +823,6 @@ startrtclock() * Curse Intel for leaving the counter out of the I/O APIC. */ -#ifdef DEV_APM /* * We can not use the TSC if we support APM. Precise timekeeping * on an APM'ed machine is at best a fools pursuit, since @@ -834,13 +833,11 @@ startrtclock() * We don't know at this point whether APM is going to be used * or not, nor when it might be activated. Play it safe. */ - { - int disabled = 0; - resource_int_value("apm", 0, "disabled", &disabled); - if (disabled == 0) + if (power_pm_get_type() == POWER_PM_TYPE_APM) { + if (bootverbose) + printf("TSC initialization skipped: APM enabled.\n"); return; } -#endif /* DEV_APM */ if (tsc_present && tsc_freq != 0 && !tsc_is_broken) { tsc_timecounter.tc_frequency = tsc_freq; diff --git a/sys/amd64/isa/clock.c b/sys/amd64/isa/clock.c index 13e11a4..a7aaea0 100644 --- a/sys/amd64/isa/clock.c +++ b/sys/amd64/isa/clock.c @@ -49,7 +49,6 @@ */ #include "opt_clock.h" -#include "opt_apm.h" #include "opt_mca.h" #include <sys/param.h> @@ -63,6 +62,7 @@ #include <sys/kernel.h> #include <sys/sysctl.h> #include <sys/cons.h> +#include <sys/power.h> #include <machine/clock.h> #ifdef CLK_CALIBRATION_LOOP @@ -823,7 +823,6 @@ startrtclock() * Curse Intel for leaving the counter out of the I/O APIC. */ -#ifdef DEV_APM /* * We can not use the TSC if we support APM. Precise timekeeping * on an APM'ed machine is at best a fools pursuit, since @@ -834,13 +833,11 @@ startrtclock() * We don't know at this point whether APM is going to be used * or not, nor when it might be activated. Play it safe. */ - { - int disabled = 0; - resource_int_value("apm", 0, "disabled", &disabled); - if (disabled == 0) + if (power_pm_get_type() == POWER_PM_TYPE_APM) { + if (bootverbose) + printf("TSC initialization skipped: APM enabled.\n"); return; } -#endif /* DEV_APM */ if (tsc_present && tsc_freq != 0 && !tsc_is_broken) { tsc_timecounter.tc_frequency = tsc_freq; diff --git a/sys/conf/files b/sys/conf/files index 79620f3..b553174 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -816,6 +816,7 @@ kern/subr_mchain.c optional libmchain kern/subr_module.c standard kern/subr_param.c standard kern/subr_pcpu.c standard +kern/subr_power.c standard kern/subr_prf.c standard kern/subr_prof.c standard kern/subr_rman.c standard 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); + diff --git a/sys/dev/syscons/syscons.c b/sys/dev/syscons/syscons.c index cf9e4b9..0a01b18 100644 --- a/sys/dev/syscons/syscons.c +++ b/sys/dev/syscons/syscons.c @@ -31,9 +31,6 @@ #include "opt_syscons.h" #include "opt_splash.h" #include "opt_ddb.h" -#ifdef __i386__ -#include "opt_apm.h" -#endif #include <sys/param.h> #include <sys/systm.h> @@ -53,6 +50,7 @@ #include <sys/signalvar.h> #include <sys/sysctl.h> #include <sys/tty.h> +#include <sys/power.h> #include <machine/clock.h> #include <machine/pc/display.h> @@ -3230,18 +3228,12 @@ next_code: #endif break; -#ifdef DEV_APM case SUSP: - apm_suspend(PMST_SUSPEND); + power_pm_suspend(POWER_SLEEP_STATE_SUSPEND); break; case STBY: - apm_suspend(PMST_STANDBY); + power_pm_suspend(POWER_SLEEP_STATE_STANDBY); break; -#else - case SUSP: - case STBY: - break; -#endif case DBG: #ifndef SC_DISABLE_DDBKEY diff --git a/sys/i386/apm/apm.c b/sys/i386/apm/apm.c index 1b7cbc5..85d4bd2 100644 --- a/sys/i386/apm/apm.c +++ b/sys/i386/apm/apm.c @@ -32,9 +32,11 @@ #include <sys/uio.h> #include <sys/signalvar.h> #include <sys/sysctl.h> +#include <sys/power.h> #include <machine/apm_bios.h> #include <machine/segments.h> #include <machine/clock.h> +#include <machine/stdarg.h> #include <vm/vm.h> #include <vm/vm_param.h> #include <vm/pmap.h> @@ -53,6 +55,8 @@ static void apm_resume __P((void)); static int apm_bioscall(void); static int apm_check_function_supported __P((u_int version, u_int func)); +static int apm_pm_func(u_long, void*, ...); + static u_long apm_version; int apm_evindex; @@ -742,6 +746,30 @@ apm_not_halt_cpu(void) /* device driver definitions */ /* + * Module event + */ + +static int +apm_modevent(struct module *mod, int event, void *junk) +{ + + switch (event) { + case MOD_LOAD: + if (!cold) + return (EPERM); + break; + case MOD_UNLOAD: + if (!cold && power_pm_get_type() == POWER_PM_TYPE_APM) + return (EBUSY); + break; + default: + break; + } + + return (0); +} + +/* * Create "connection point" */ static void @@ -749,6 +777,11 @@ apm_identify(driver_t *driver, device_t parent) { device_t child; + if (!cold) { + printf("Don't load this driver from userland!!\n"); + return; + } + child = BUS_ADD_CHILD(parent, 0, "apm", 0); if (child == NULL) panic("apm_identify"); @@ -777,6 +810,12 @@ apm_probe(device_t dev) return ENXIO; } + if (power_pm_get_type() != POWER_PM_TYPE_NONE && + power_pm_get_type() != POWER_PM_TYPE_APM) { + printf("apm: Other PM system enabled.\n"); + return ENXIO; + } + if (resource_int_value("apm", 0, "flags", &flags) != 0) flags = 0; @@ -1038,10 +1077,13 @@ apm_attach(device_t dev) EVENTHANDLER_REGISTER(shutdown_final, apm_power_off, NULL, SHUTDOWN_PRI_LAST); + /* Register APM again to pass the correct argument of pm_func. */ + power_pm_register(POWER_PM_TYPE_APM, apm_pm_func, sc); + sc->initialized = 1; sc->suspending = 0; - make_dev(&apm_cdevsw, 0, 0, 5, 0660, "apm"); + make_dev(&apm_cdevsw, 0, 0, 5, 0664, "apm"); make_dev(&apm_cdevsw, 8, 0, 5, 0660, "apmctl"); return 0; } @@ -1315,4 +1357,56 @@ static driver_t apm_driver = { static devclass_t apm_devclass; -DRIVER_MODULE(apm, nexus, apm_driver, apm_devclass, 0, 0); +DRIVER_MODULE(apm, nexus, apm_driver, apm_devclass, apm_modevent, 0); +MODULE_VERSION(apm, 1); + +static int +apm_pm_func(u_long cmd, void *arg, ...) +{ + int state, apm_state; + int error; + va_list ap; + + error = 0; + switch (cmd) { + case POWER_CMD_SUSPEND: + va_start(ap, arg); + state = va_arg(ap, int); + va_end(ap); + + switch (state) { + case POWER_SLEEP_STATE_STANDBY: + apm_state = PMST_STANDBY; + break; + case POWER_SLEEP_STATE_SUSPEND: + case POWER_SLEEP_STATE_HIBERNATE: + apm_state = PMST_SUSPEND; + break; + default: + error = EINVAL; + goto out; + } + + apm_suspend(apm_state); + break; + + default: + error = EINVAL; + goto out; + } + +out: + return (error); +} + +static void +apm_pm_register(void *arg) +{ + int disabled = 0; + + resource_int_value("apm", 0, "disabled", &disabled); + if (disabled == 0) + power_pm_register(POWER_PM_TYPE_APM, apm_pm_func, NULL); +} + +SYSINIT(power, SI_SUB_KLD, SI_ORDER_ANY, apm_pm_register, 0); diff --git a/sys/i386/bios/apm.c b/sys/i386/bios/apm.c index 1b7cbc5..85d4bd2 100644 --- a/sys/i386/bios/apm.c +++ b/sys/i386/bios/apm.c @@ -32,9 +32,11 @@ #include <sys/uio.h> #include <sys/signalvar.h> #include <sys/sysctl.h> +#include <sys/power.h> #include <machine/apm_bios.h> #include <machine/segments.h> #include <machine/clock.h> +#include <machine/stdarg.h> #include <vm/vm.h> #include <vm/vm_param.h> #include <vm/pmap.h> @@ -53,6 +55,8 @@ static void apm_resume __P((void)); static int apm_bioscall(void); static int apm_check_function_supported __P((u_int version, u_int func)); +static int apm_pm_func(u_long, void*, ...); + static u_long apm_version; int apm_evindex; @@ -742,6 +746,30 @@ apm_not_halt_cpu(void) /* device driver definitions */ /* + * Module event + */ + +static int +apm_modevent(struct module *mod, int event, void *junk) +{ + + switch (event) { + case MOD_LOAD: + if (!cold) + return (EPERM); + break; + case MOD_UNLOAD: + if (!cold && power_pm_get_type() == POWER_PM_TYPE_APM) + return (EBUSY); + break; + default: + break; + } + + return (0); +} + +/* * Create "connection point" */ static void @@ -749,6 +777,11 @@ apm_identify(driver_t *driver, device_t parent) { device_t child; + if (!cold) { + printf("Don't load this driver from userland!!\n"); + return; + } + child = BUS_ADD_CHILD(parent, 0, "apm", 0); if (child == NULL) panic("apm_identify"); @@ -777,6 +810,12 @@ apm_probe(device_t dev) return ENXIO; } + if (power_pm_get_type() != POWER_PM_TYPE_NONE && + power_pm_get_type() != POWER_PM_TYPE_APM) { + printf("apm: Other PM system enabled.\n"); + return ENXIO; + } + if (resource_int_value("apm", 0, "flags", &flags) != 0) flags = 0; @@ -1038,10 +1077,13 @@ apm_attach(device_t dev) EVENTHANDLER_REGISTER(shutdown_final, apm_power_off, NULL, SHUTDOWN_PRI_LAST); + /* Register APM again to pass the correct argument of pm_func. */ + power_pm_register(POWER_PM_TYPE_APM, apm_pm_func, sc); + sc->initialized = 1; sc->suspending = 0; - make_dev(&apm_cdevsw, 0, 0, 5, 0660, "apm"); + make_dev(&apm_cdevsw, 0, 0, 5, 0664, "apm"); make_dev(&apm_cdevsw, 8, 0, 5, 0660, "apmctl"); return 0; } @@ -1315,4 +1357,56 @@ static driver_t apm_driver = { static devclass_t apm_devclass; -DRIVER_MODULE(apm, nexus, apm_driver, apm_devclass, 0, 0); +DRIVER_MODULE(apm, nexus, apm_driver, apm_devclass, apm_modevent, 0); +MODULE_VERSION(apm, 1); + +static int +apm_pm_func(u_long cmd, void *arg, ...) +{ + int state, apm_state; + int error; + va_list ap; + + error = 0; + switch (cmd) { + case POWER_CMD_SUSPEND: + va_start(ap, arg); + state = va_arg(ap, int); + va_end(ap); + + switch (state) { + case POWER_SLEEP_STATE_STANDBY: + apm_state = PMST_STANDBY; + break; + case POWER_SLEEP_STATE_SUSPEND: + case POWER_SLEEP_STATE_HIBERNATE: + apm_state = PMST_SUSPEND; + break; + default: + error = EINVAL; + goto out; + } + + apm_suspend(apm_state); + break; + + default: + error = EINVAL; + goto out; + } + +out: + return (error); +} + +static void +apm_pm_register(void *arg) +{ + int disabled = 0; + + resource_int_value("apm", 0, "disabled", &disabled); + if (disabled == 0) + power_pm_register(POWER_PM_TYPE_APM, apm_pm_func, NULL); +} + +SYSINIT(power, SI_SUB_KLD, SI_ORDER_ANY, apm_pm_register, 0); diff --git a/sys/i386/i386/tsc.c b/sys/i386/i386/tsc.c index 13e11a4..a7aaea0 100644 --- a/sys/i386/i386/tsc.c +++ b/sys/i386/i386/tsc.c @@ -49,7 +49,6 @@ */ #include "opt_clock.h" -#include "opt_apm.h" #include "opt_mca.h" #include <sys/param.h> @@ -63,6 +62,7 @@ #include <sys/kernel.h> #include <sys/sysctl.h> #include <sys/cons.h> +#include <sys/power.h> #include <machine/clock.h> #ifdef CLK_CALIBRATION_LOOP @@ -823,7 +823,6 @@ startrtclock() * Curse Intel for leaving the counter out of the I/O APIC. */ -#ifdef DEV_APM /* * We can not use the TSC if we support APM. Precise timekeeping * on an APM'ed machine is at best a fools pursuit, since @@ -834,13 +833,11 @@ startrtclock() * We don't know at this point whether APM is going to be used * or not, nor when it might be activated. Play it safe. */ - { - int disabled = 0; - resource_int_value("apm", 0, "disabled", &disabled); - if (disabled == 0) + if (power_pm_get_type() == POWER_PM_TYPE_APM) { + if (bootverbose) + printf("TSC initialization skipped: APM enabled.\n"); return; } -#endif /* DEV_APM */ if (tsc_present && tsc_freq != 0 && !tsc_is_broken) { tsc_timecounter.tc_frequency = tsc_freq; diff --git a/sys/i386/isa/clock.c b/sys/i386/isa/clock.c index 13e11a4..a7aaea0 100644 --- a/sys/i386/isa/clock.c +++ b/sys/i386/isa/clock.c @@ -49,7 +49,6 @@ */ #include "opt_clock.h" -#include "opt_apm.h" #include "opt_mca.h" #include <sys/param.h> @@ -63,6 +62,7 @@ #include <sys/kernel.h> #include <sys/sysctl.h> #include <sys/cons.h> +#include <sys/power.h> #include <machine/clock.h> #ifdef CLK_CALIBRATION_LOOP @@ -823,7 +823,6 @@ startrtclock() * Curse Intel for leaving the counter out of the I/O APIC. */ -#ifdef DEV_APM /* * We can not use the TSC if we support APM. Precise timekeeping * on an APM'ed machine is at best a fools pursuit, since @@ -834,13 +833,11 @@ startrtclock() * We don't know at this point whether APM is going to be used * or not, nor when it might be activated. Play it safe. */ - { - int disabled = 0; - resource_int_value("apm", 0, "disabled", &disabled); - if (disabled == 0) + if (power_pm_get_type() == POWER_PM_TYPE_APM) { + if (bootverbose) + printf("TSC initialization skipped: APM enabled.\n"); return; } -#endif /* DEV_APM */ if (tsc_present && tsc_freq != 0 && !tsc_is_broken) { tsc_timecounter.tc_frequency = tsc_freq; diff --git a/sys/isa/atrtc.c b/sys/isa/atrtc.c index 13e11a4..a7aaea0 100644 --- a/sys/isa/atrtc.c +++ b/sys/isa/atrtc.c @@ -49,7 +49,6 @@ */ #include "opt_clock.h" -#include "opt_apm.h" #include "opt_mca.h" #include <sys/param.h> @@ -63,6 +62,7 @@ #include <sys/kernel.h> #include <sys/sysctl.h> #include <sys/cons.h> +#include <sys/power.h> #include <machine/clock.h> #ifdef CLK_CALIBRATION_LOOP @@ -823,7 +823,6 @@ startrtclock() * Curse Intel for leaving the counter out of the I/O APIC. */ -#ifdef DEV_APM /* * We can not use the TSC if we support APM. Precise timekeeping * on an APM'ed machine is at best a fools pursuit, since @@ -834,13 +833,11 @@ startrtclock() * We don't know at this point whether APM is going to be used * or not, nor when it might be activated. Play it safe. */ - { - int disabled = 0; - resource_int_value("apm", 0, "disabled", &disabled); - if (disabled == 0) + if (power_pm_get_type() == POWER_PM_TYPE_APM) { + if (bootverbose) + printf("TSC initialization skipped: APM enabled.\n"); return; } -#endif /* DEV_APM */ if (tsc_present && tsc_freq != 0 && !tsc_is_broken) { tsc_timecounter.tc_frequency = tsc_freq; diff --git a/sys/kern/subr_power.c b/sys/kern/subr_power.c new file mode 100644 index 0000000..d73958c --- /dev/null +++ b/sys/kern/subr_power.c @@ -0,0 +1,76 @@ +/*- + * 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/systm.h> + +#include <sys/power.h> + +static u_int power_pm_type = POWER_PM_TYPE_NONE; +static power_pm_fn_t power_pm_fn = NULL; +static void *power_pm_arg = NULL; + +int +power_pm_register(u_int pm_type, power_pm_fn_t pm_fn, void *pm_arg) +{ + int error; + + if (power_pm_type == POWER_PM_TYPE_NONE || + power_pm_type == pm_type) { + power_pm_type = pm_type; + power_pm_fn = pm_fn; + power_pm_arg = pm_arg; + error = 0; + } else { + error = ENXIO; + } + + return (error); +} + +u_int +power_pm_get_type(void) +{ + + return (power_pm_type); +} + +void +power_pm_suspend(int state) +{ + if (power_pm_fn == NULL) + return; + + if (state != POWER_SLEEP_STATE_STANDBY && + state != POWER_SLEEP_STATE_SUSPEND && + state != POWER_SLEEP_STATE_HIBERNATE) + return; + + power_pm_fn(POWER_CMD_SUSPEND, power_pm_arg, state); +} + diff --git a/sys/sys/kernel.h b/sys/sys/kernel.h index 61faad3..e1972d4 100644 --- a/sys/sys/kernel.h +++ b/sys/sys/kernel.h @@ -119,8 +119,8 @@ enum sysinit_sub_id { SI_SUB_WITNESS = 0x1A80000, /* witness initialization */ SI_SUB_LOCK = 0x1B00000, /* lockmgr locks */ SI_SUB_EVENTHANDLER = 0x1C00000, /* eventhandler init */ - SI_SUB_CPU = 0x2000000, /* CPU resource(s)*/ - SI_SUB_KLD = 0x2100000, /* KLD and module setup */ + SI_SUB_KLD = 0x2000000, /* KLD and module setup */ + SI_SUB_CPU = 0x2100000, /* CPU resource(s)*/ SI_SUB_INTRINSIC = 0x2200000, /* proc 0*/ SI_SUB_VM_CONF = 0x2300000, /* config VM, set limits*/ SI_SUB_RUN_QUEUE = 0x2400000, /* set up run queue*/ diff --git a/sys/sys/power.h b/sys/sys/power.h new file mode 100644 index 0000000..a94ed06 --- /dev/null +++ b/sys/sys/power.h @@ -0,0 +1,51 @@ +/*- + * 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$ + */ + +#ifndef _SYS_POWER_H_ +#define _SYS_POWER_H_ + +/* Power management system type */ +#define POWER_PM_TYPE_APM 0x00 +#define POWER_PM_TYPE_ACPI 0x01 +#define POWER_PM_TYPE_NONE 0xff + +/* Commands for Power management function */ +#define POWER_CMD_SUSPEND 0x00 + +/* Sleep state */ +#define POWER_SLEEP_STATE_STANDBY 0x00 +#define POWER_SLEEP_STATE_SUSPEND 0x01 +#define POWER_SLEEP_STATE_HIBERNATE 0x02 + +typedef int (*power_pm_fn_t)(u_long, void*, ...); +extern int power_pm_register(u_int, power_pm_fn_t, void *); +extern u_int power_pm_get_type(void); +extern void power_pm_suspend(int); + +#endif /* !_SYS_POWER_H_ */ + |