diff options
author | iwasaki <iwasaki@FreeBSD.org> | 2000-09-14 23:29:37 +0000 |
---|---|---|
committer | iwasaki <iwasaki@FreeBSD.org> | 2000-09-14 23:29:37 +0000 |
commit | 9a638b9d568eed5d66f28bd4873fd23fb10ec271 (patch) | |
tree | 787a95240edba67fe55891d615c83772f0dc0254 /sys/dev | |
parent | 48aa25a6f65fca2b6b8f868f95c262cc0cc99b73 (diff) | |
download | FreeBSD-src-9a638b9d568eed5d66f28bd4873fd23fb10ec271.zip FreeBSD-src-9a638b9d568eed5d66f28bd4873fd23fb10ec271.tar.gz |
Add acpi_send_pm_event() to inform all devices that the system is
going to sleep and back from sleep.
Also re-enabling some acpi registers on wakeup.
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/acpi/acpi.c | 60 | ||||
-rw-r--r-- | sys/dev/acpi/acpi.h | 6 |
2 files changed, 63 insertions, 3 deletions
diff --git a/sys/dev/acpi/acpi.c b/sys/dev/acpi/acpi.c index 0ebbf83..a8b84a3 100644 --- a/sys/dev/acpi/acpi.c +++ b/sys/dev/acpi/acpi.c @@ -36,6 +36,9 @@ #include <sys/conf.h> #include <sys/sysctl.h> +#include <vm/vm.h> +#include <vm/pmap.h> + #include <sys/eventhandler.h> /* for EVENTHANDLER_REGISTER */ #include <sys/reboot.h> /* for RB_POWEROFF */ #include <machine/clock.h> /* for DELAY */ @@ -153,6 +156,7 @@ static void acpi_enable_events(acpi_softc_t *sc); /* New-bus dependent code */ static acpi_softc_t *acpi_get_softc(dev_t dev); +static int acpi_send_pm_event(acpi_softc_t *sc, u_int8_t state); static void acpi_identify(driver_t *driver, device_t parent); static int acpi_probe(device_t dev); static int acpi_attach(device_t dev); @@ -374,6 +378,7 @@ acpi_enable_disable(acpi_softc_t *sc, boolean_t enable) } bus_space_write_1(bst, bsh, 0, val); + sc->enabled = enable; ACPI_DEBUGPRINT("acpi_enable_disable(%d) = (%x)\n", enable, val); } @@ -680,6 +685,7 @@ acpi_handle_dsdt(acpi_softc_t *sc) } /* get sleeping type values from ACPI namespace */ + sc->system_state = ACPI_S_STATE_S0; sc->system_state_initialized = 1; for (i = ACPI_S_STATE_S0; i <= ACPI_S_STATE_S5; i++) { ssp.mode[i].slp_typ_a = ACPI_UNSUPPORTSLPTYP; @@ -904,6 +910,13 @@ acpi_set_sleeping_state(acpi_softc_t *sc, u_int8_t state) } if (state < ACPI_S_STATE_S5) { + /* inform all devices that we are going to sleep. */ + if (acpi_send_pm_event(sc, state) != 0) { + /* if failure, 'wakeup' the system again */ + acpi_send_pm_event(sc, ACPI_S_STATE_S0); + return; + } + /* Prepare to sleep */ acpi_execute_pts(sc, state); @@ -912,6 +925,8 @@ acpi_set_sleeping_state(acpi_softc_t *sc, u_int8_t state) if (acpi_debug) { acpi_powerres_debug(sc); } + + sc->system_state = state; } /* @@ -931,11 +946,14 @@ acpi_set_sleeping_state(acpi_softc_t *sc, u_int8_t state) } if (state < ACPI_S_STATE_S5) { - acpi_execute_wak(sc, state); acpi_powerres_set_sleeping_state(sc, 0); if (acpi_debug) { acpi_powerres_debug(sc); } + acpi_execute_wak(sc, state); + acpi_send_pm_event(sc, ACPI_S_STATE_S0); + + sc->system_state = ACPI_S_STATE_S0; } } @@ -1233,6 +1251,31 @@ acpi_get_softc(dev_t dev) return (devclass_get_softc(acpi_devclass, minor(dev))); } +static int +acpi_send_pm_event(acpi_softc_t *sc, u_int8_t state) +{ + int error; + + error = 0; + switch (state) { + case ACPI_S_STATE_S0: + if (sc->system_state != ACPI_S_STATE_S0) { + DEVICE_RESUME(root_bus); + } + break; + case ACPI_S_STATE_S1: + case ACPI_S_STATE_S2: + case ACPI_S_STATE_S3: + case ACPI_S_STATE_S4: + error = DEVICE_SUSPEND(root_bus); + break; + default: + break; + } + + return (error); +} + static void acpi_identify(driver_t *driver, device_t parent) { @@ -1342,11 +1385,26 @@ acpi_attach(device_t dev) return (0); } +static int +acpi_resume(device_t dev) +{ + acpi_softc_t *sc; + + sc = device_get_softc(dev); + if (sc->enabled) { + /* re-enable on wakeup */ + acpi_enable_disable(sc, 1); + acpi_enable_events(sc); + } + return (0); +} + static device_method_t acpi_methods[] = { /* Device interface */ DEVMETHOD(device_identify, acpi_identify), DEVMETHOD(device_probe, acpi_probe), DEVMETHOD(device_attach, acpi_attach), + DEVMETHOD(device_resume, acpi_resume), {0, 0} }; diff --git a/sys/dev/acpi/acpi.h b/sys/dev/acpi/acpi.h index 4e1887b..5c4cb2e 100644 --- a/sys/dev/acpi/acpi.h +++ b/sys/dev/acpi/acpi.h @@ -53,7 +53,7 @@ struct acpi_powerres_info { #define ACPI_POWER_RESOURCE_ON 1 #define ACPI_POWER_RESOURCE_OFF 0 u_int8_t state; /* OFF or ON */ -#define ACPI_PR_MAX 3 +#define ACPI_PR_MAX 3 /* _PR[0-2] */ LIST_HEAD(, acpi_powerres_device_ref) reflist[ACPI_PR_MAX]; }; @@ -64,8 +64,10 @@ typedef struct acpi_softc { struct FACPbody *facp_body; struct ACPIsdt *dsdt; struct FACS *facs; + int system_state; int system_state_initialized; int broken_wakeuplogic; + int enabled; struct acpi_system_state_package system_state_package; LIST_HEAD(, acpi_powerres_info) acpi_powerres_inflist; LIST_HEAD(, acpi_powerres_device) acpi_powerres_devlist; @@ -84,4 +86,4 @@ void acpi_set_powerres_state(acpi_softc_t *, struct aml_name *, u_int8_t); void acpi_powerres_set_sleeping_state(acpi_softc_t *, u_int8_t); -#endif /* _DEV_ACPI_ACPI_H_ */ +#endif /* !_DEV_ACPI_ACPI_H_ */ |