summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoriwasaki <iwasaki@FreeBSD.org>2001-11-01 16:34:07 +0000
committeriwasaki <iwasaki@FreeBSD.org>2001-11-01 16:34:07 +0000
commitf1842a13d838c3a94044961bbf70910f54a49956 (patch)
tree386182cbb6b07e9a3fa20ca8415118c34d61ecae
parent9440591aaa9e7f2d8ef542a245eb93b2c2547844 (diff)
downloadFreeBSD-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@
-rw-r--r--sys/amd64/amd64/tsc.c11
-rw-r--r--sys/amd64/isa/clock.c11
-rw-r--r--sys/conf/files1
-rw-r--r--sys/dev/acpica/acpi.c75
-rw-r--r--sys/dev/syscons/syscons.c14
-rw-r--r--sys/i386/apm/apm.c98
-rw-r--r--sys/i386/bios/apm.c98
-rw-r--r--sys/i386/i386/tsc.c11
-rw-r--r--sys/i386/isa/clock.c11
-rw-r--r--sys/isa/atrtc.c11
-rw-r--r--sys/kern/subr_power.c76
-rw-r--r--sys/sys/kernel.h4
-rw-r--r--sys/sys/power.h51
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_ */
+
OpenPOWER on IntegriCloud