diff --git a/sys/amd64/amd64/tsc.c b/sys/amd64/amd64/tsc.c index 13e11a4315a2..a7aaea0b7a5e 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 @@ -63,6 +62,7 @@ #include #include #include +#include #include #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 13e11a4315a2..a7aaea0b7a5e 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 @@ -63,6 +62,7 @@ #include #include #include +#include #include #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 79620f3e816a..b5531747ae1f 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 f930e028abd3..17987f0401c4 100644 --- a/sys/dev/acpica/acpi.c +++ b/sys/dev/acpica/acpi.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #include @@ -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 cf9e4b9a5399..0a01b183c5d9 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 #include @@ -53,6 +50,7 @@ #include #include #include +#include #include #include @@ -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 1b7cbc5101f3..85d4bd2b2ddb 100644 --- a/sys/i386/apm/apm.c +++ b/sys/i386/apm/apm.c @@ -32,9 +32,11 @@ #include #include #include +#include #include #include #include +#include #include #include #include @@ -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; @@ -741,6 +745,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" */ @@ -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 1b7cbc5101f3..85d4bd2b2ddb 100644 --- a/sys/i386/bios/apm.c +++ b/sys/i386/bios/apm.c @@ -32,9 +32,11 @@ #include #include #include +#include #include #include #include +#include #include #include #include @@ -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; @@ -741,6 +745,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" */ @@ -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 13e11a4315a2..a7aaea0b7a5e 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 @@ -63,6 +62,7 @@ #include #include #include +#include #include #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 13e11a4315a2..a7aaea0b7a5e 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 @@ -63,6 +62,7 @@ #include #include #include +#include #include #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 13e11a4315a2..a7aaea0b7a5e 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 @@ -63,6 +62,7 @@ #include #include #include +#include #include #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 000000000000..d73958c9681d --- /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 +#include + +#include + +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 61faad345e80..e1972d44ab53 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 000000000000..a94ed06ae49b --- /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_ */ +