+++ /dev/null
-/*
- * acpi_system.c - ACPI System Driver ($Revision: 57 $)
- *
- * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
- * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- */
-
-/* Modified for ReactOS and latest ACPICA
- * Copyright (C)2009 Samuel Serapion
- */
-
-#include <precomp.h>
-
-#define NDEBUG
-#include <debug.h>
-
-ACPI_STATUS acpi_system_save_state(UINT32);
-
-#define _COMPONENT ACPI_SYSTEM_COMPONENT
-ACPI_MODULE_NAME ("acpi_system")
-
-#define PREFIX "ACPI: "
-
-static int acpi_system_add (struct acpi_device *device);
-static int acpi_system_remove (struct acpi_device *device, int type);
-
-ACPI_STATUS acpi_suspend (UINT32 state);
-
-static struct acpi_driver acpi_system_driver = {
- {0,0},
- ACPI_SYSTEM_DRIVER_NAME,
- ACPI_SYSTEM_CLASS,
- 0,
- 0,
- ACPI_SYSTEM_HID,
- {acpi_system_add, acpi_system_remove}
-};
-
-struct acpi_system
-{
- ACPI_HANDLE handle;
- UINT8 states[ACPI_S_STATE_COUNT];
-};
-
-
-static int
-acpi_system_add (
- struct acpi_device *device)
-{
- ACPI_STATUS status = AE_OK;
- struct acpi_system *system = NULL;
- UINT8 i = 0;
-
- ACPI_FUNCTION_TRACE("acpi_system_add");
-
- if (!device)
- return_VALUE(-1);
-
- system = ExAllocatePoolWithTag(NonPagedPool,sizeof(struct acpi_system),'IPCA');
- if (!system)
- return_VALUE(-14);
- memset(system, 0, sizeof(struct acpi_system));
-
- system->handle = device->handle;
- sprintf(acpi_device_name(device), "%s", ACPI_SYSTEM_DEVICE_NAME);
- sprintf(acpi_device_class(device), "%s", ACPI_SYSTEM_CLASS);
- acpi_driver_data(device) = system;
-
- DPRINT("%s [%s] (supports",
- acpi_device_name(device), acpi_device_bid(device));
- for (i=0; i<ACPI_S_STATE_COUNT; i++) {
- UINT8 type_a, type_b;
- status = AcpiGetSleepTypeData(i, &type_a, &type_b);
- switch (i) {
- case ACPI_STATE_S4:
- if (/*AcpiGbl_FACS->S4bios_f &&*/
- 0 != AcpiGbl_FADT.SmiCommand) {
- DPRINT(" S4bios\n");
- system->states[i] = 1;
- }
- /* no break */
- default:
- if (ACPI_SUCCESS(status)) {
- system->states[i] = 1;
- DPRINT(" S%d", i);
- }
- }
- }
-
-//#ifdef CONFIG_PM
-// /* Install the soft-off (S5) handler. */
-// if (system->states[ACPI_STATE_S5]) {
-// pm_power_off = acpi_power_off;
-// register_sysrq_key('o', &sysrq_acpi_poweroff_op);
-// }
-//#endif
-
- return_VALUE(0);
-}
-
-static int
-acpi_system_remove (
- struct acpi_device *device,
- int type)
-{
- struct acpi_system *system = NULL;
-
- ACPI_FUNCTION_TRACE("acpi_system_remove");
-
- if (!device || !acpi_driver_data(device))
- return_VALUE(-1);
-
- system = (struct acpi_system *) acpi_driver_data(device);
-
-//#ifdef CONFIG_PM
-// /* Remove the soft-off (S5) handler. */
-// if (system->states[ACPI_STATE_S5]) {
-// unregister_sysrq_key('o', &sysrq_acpi_poweroff_op);
-// pm_power_off = NULL;
-// }
-//#endif
-//
-//
- ExFreePoolWithTag(system, 'IPCA');
-
- return 0;
-}
-
-/**
- * acpi_system_restore_state - OS-specific restoration of state
- * @state: sleep state we're exiting
- *
- * Note that if we're coming back from S4, the memory image should have
- * already been loaded from the disk and is already in place. (Otherwise how
- * else would we be here?).
- */
-ACPI_STATUS
-acpi_system_restore_state(
- UINT32 state)
-{
- /*
- * We should only be here if we're coming back from STR or STD.
- * And, in the case of the latter, the memory image should have already
- * been loaded from disk.
- */
- if (state > ACPI_STATE_S1) {
- //acpi_restore_state_mem();
-
- /* Do _early_ resume for irqs. Required by
- * ACPI specs.
- */
- /* TBD: call arch dependant reinitialization of the
- * interrupts.
- */
-#ifdef _X86_
- //init_8259A(0);
-#endif
- /* wait for power to come back */
- KeStallExecutionProcessor(100);
-
- }
-
- /* Be really sure that irqs are disabled. */
- //ACPI_DISABLE_IRQS();
-
- /* Wait a little again, just in case... */
- KeStallExecutionProcessor(10);
-
- /* enable interrupts once again */
- //ACPI_ENABLE_IRQS();
-
- /* turn all the devices back on */
- //if (state > ACPI_STATE_S1)
- //pm_send_all(PM_RESUME, (void *)0);
-
- return AE_OK;
-}
-
-
-/**
- * acpi_system_save_state - save OS specific state and power down devices
- * @state: sleep state we're entering.
- *
- * This handles saving all context to memory, and possibly disk.
- * First, we call to the device driver layer to save device state.
- * Once we have that, we save whatevery processor and kernel state we
- * need to memory.
- * If we're entering S4, we then write the memory image to disk.
- *
- * Only then it is safe for us to power down devices, since we may need
- * the disks and upstream buses to write to.
- */
-ACPI_STATUS
-acpi_system_save_state(
- UINT32 state)
-{
- int error = 0;
-
- /* Send notification to devices that they will be suspended.
- * If any device or driver cannot make the transition, either up
- * or down, we'll get an error back.
- */
- /*if (state > ACPI_STATE_S1) {
- error = pm_send_all(PM_SAVE_STATE, (void *)3);
- if (error)
- return AE_ERROR;
- }*/
-
- //if (state <= ACPI_STATE_S5) {
- // /* Tell devices to stop I/O and actually save their state.
- // * It is theoretically possible that something could fail,
- // * so handle that gracefully..
- // */
- // if (state > ACPI_STATE_S1 && state != ACPI_STATE_S5) {
- // error = pm_send_all(PM_SUSPEND, (void *)3);
- // if (error) {
- // /* Tell devices to restore state if they have
- // * it saved and to start taking I/O requests.
- // */
- // pm_send_all(PM_RESUME, (void *)0);
- // return error;
- // }
- // }
-
- /* flush caches */
- ACPI_FLUSH_CPU_CACHE();
-
- /* Do arch specific saving of state. */
- if (state > ACPI_STATE_S1) {
- error = 0;//acpi_save_state_mem();
-
- /* TBD: if no s4bios, write codes for
- * acpi_save_state_disk()...
- */
-#if 0
- if (!error && (state == ACPI_STATE_S4))
- error = acpi_save_state_disk();
-#endif
- /*if (error) {
- pm_send_all(PM_RESUME, (void *)0);
- return error;
- }*/
- }
- //}
- /* disable interrupts
- * Note that acpi_suspend -- our caller -- will do this once we return.
- * But, we want it done early, so we don't get any surprises during
- * the device suspend sequence.
- */
- //ACPI_DISABLE_IRQS();
-
- /* Unconditionally turn off devices.
- * Obvious if we enter a sleep state.
- * If entering S5 (soft off), this should put devices in a
- * quiescent state.
- */
-
- //if (state > ACPI_STATE_S1) {
- // error = pm_send_all(PM_SUSPEND, (void *)3);
-
- // /* We're pretty screwed if we got an error from this.
- // * We try to recover by simply calling our own restore_state
- // * function; see above for definition.
- // *
- // * If it's S5 though, go through with it anyway..
- // */
- // if (error && state != ACPI_STATE_S5)
- // acpi_system_restore_state(state);
- //}
- return error ? AE_ERROR : AE_OK;
-}
-
-
-/****************************************************************************
- *
- * FUNCTION: acpi_system_suspend
- *
- * PARAMETERS: %state: Sleep state to enter.
- *
- * RETURN: ACPI_STATUS, whether or not we successfully entered and
- * exited sleep.
- *
- * DESCRIPTION: Perform OS-specific action to enter sleep state.
- * This is the final step in going to sleep, per spec. If we
- * know we're coming back (i.e. not entering S5), we save the
- * processor flags. [ We'll have to save and restore them anyway,
- * so we use the arch-agnostic save_flags and restore_flags
- * here.] We then set the place to return to in arch-specific
- * globals using arch_set_return_point. Finally, we call the
- * ACPI function to write the proper values to I/O ports.
- *
- ****************************************************************************/
-
-ACPI_STATUS
-acpi_system_suspend(
- UINT32 state)
-{
- ACPI_STATUS status = AE_ERROR;
- //unsigned long flags = 0;
-
- //local_irq_save(flags);
- /* kernel_fpu_begin(); */
-
- switch (state) {
- case ACPI_STATE_S1:
- case ACPI_STATE_S5:
- //barrier();
- status = AcpiEnterSleepState(state);
- break;
- case ACPI_STATE_S4:
- //do_suspend_lowlevel_s4bios(0);
- break;
- }
-
- /* kernel_fpu_end(); */
- //local_irq_restore(flags);
-
- return status;
-}
-
-
-
-/**
- * acpi_suspend - OS-agnostic system suspend/resume support (S? states)
- * @state: state we're entering
- *
- */
-ACPI_STATUS
-acpi_suspend (
- UINT32 state)
-{
- ACPI_STATUS status;
-
- /* only support S1 and S5 on kernel 2.4 */
- //if (state != ACPI_STATE_S1 && state != ACPI_STATE_S4
- // && state != ACPI_STATE_S5)
- // return AE_ERROR;
-
-
- //if (ACPI_STATE_S4 == state) {
- // /* For s4bios, we need a wakeup address. */
- // if (1 == AcpiGbl_FACS->S4bios_f &&
- // 0 != AcpiGbl_FADT->smi_cmd) {
- // if (!acpi_wakeup_address)
- // return AE_ERROR;
- // AcpiSetFirmwareWakingVector((acpi_physical_address) acpi_wakeup_address);
- // } else
- // /* We don't support S4 under 2.4. Give up */
- // return AE_ERROR;
- //}
- AcpiEnterSleepStatePrep(state);
-
- status = AcpiEnterSleepState(state);
- if (!ACPI_SUCCESS(status) && state != ACPI_STATE_S5)
- return status;
-
- /* disable interrupts and flush caches */
- _disable();
- ACPI_FLUSH_CPU_CACHE();
-
- /* perform OS-specific sleep actions */
- status = acpi_system_suspend(state);
-
- /* Even if we failed to go to sleep, all of the devices are in an suspended
- * mode. So, we run these unconditionally to make sure we have a usable system
- * no matter what.
- */
- AcpiLeaveSleepState(state);
- acpi_system_restore_state(state);
-
- /* make sure interrupts are enabled */
- _enable();
-
- /* reset firmware waking vector */
- AcpiSetFirmwareWakingVector(0, 0);
-
- return status;
-}
-
-int
-acpi_system_init (void)
-{
- int result = 0;
-
- ACPI_FUNCTION_TRACE("acpi_system_init");
-
- result = acpi_bus_register_driver(&acpi_system_driver);
- if (result < 0)
- return_VALUE(AE_NOT_FOUND);
-
- return_VALUE(0);
-}
-
-
-void
-acpi_system_exit (void)
-{
- ACPI_FUNCTION_TRACE("acpi_system_exit");
- acpi_bus_unregister_driver(&acpi_system_driver);
- return_VOID;
-}
-