hwsleep.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:7k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /******************************************************************************
  2.  *
  3.  * Name: hwsleep.c - ACPI Hardware Sleep/Wake Interface
  4.  *              $Revision: 22 $
  5.  *
  6.  *****************************************************************************/
  7. /*
  8.  *  Copyright (C) 2000, 2001 R. Byron Moore
  9.  *
  10.  *  This program is free software; you can redistribute it and/or modify
  11.  *  it under the terms of the GNU General Public License as published by
  12.  *  the Free Software Foundation; either version 2 of the License, or
  13.  *  (at your option) any later version.
  14.  *
  15.  *  This program is distributed in the hope that it will be useful,
  16.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  *  GNU General Public License for more details.
  19.  *
  20.  *  You should have received a copy of the GNU General Public License
  21.  *  along with this program; if not, write to the Free Software
  22.  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  23.  */
  24. #include "acpi.h"
  25. #include "acnamesp.h"
  26. #include "achware.h"
  27. #define _COMPONENT          ACPI_HARDWARE
  28.  MODULE_NAME         ("hwsleep")
  29. /******************************************************************************
  30.  *
  31.  * FUNCTION:    Acpi_set_firmware_waking_vector
  32.  *
  33.  * PARAMETERS:  Physical_address    - Physical address of ACPI real mode
  34.  *                                    entry point.
  35.  *
  36.  * RETURN:      AE_OK or AE_ERROR
  37.  *
  38.  * DESCRIPTION: Access function for d_firmware_waking_vector field in FACS
  39.  *
  40.  ******************************************************************************/
  41. acpi_status
  42. acpi_set_firmware_waking_vector (
  43. ACPI_PHYSICAL_ADDRESS physical_address)
  44. {
  45. FUNCTION_TRACE ("Acpi_set_firmware_waking_vector");
  46. /* Make sure that we have an FACS */
  47. if (!acpi_gbl_FACS) {
  48. return_ACPI_STATUS (AE_NO_ACPI_TABLES);
  49. }
  50. /* Set the vector */
  51. if (acpi_gbl_FACS->vector_width == 32) {
  52. * (u32 *) acpi_gbl_FACS->firmware_waking_vector = (u32) physical_address;
  53. }
  54. else {
  55. *acpi_gbl_FACS->firmware_waking_vector = physical_address;
  56. }
  57. return_ACPI_STATUS (AE_OK);
  58. }
  59. /******************************************************************************
  60.  *
  61.  * FUNCTION:    Acpi_get_firmware_waking_vector
  62.  *
  63.  * PARAMETERS:  *Physical_address   - Output buffer where contents of
  64.  *                                    the Firmware_waking_vector field of
  65.  *                                    the FACS will be stored.
  66.  *
  67.  * RETURN:      Status
  68.  *
  69.  * DESCRIPTION: Access function for d_firmware_waking_vector field in FACS
  70.  *
  71.  ******************************************************************************/
  72. acpi_status
  73. acpi_get_firmware_waking_vector (
  74. ACPI_PHYSICAL_ADDRESS *physical_address)
  75. {
  76. FUNCTION_TRACE ("Acpi_get_firmware_waking_vector");
  77. if (!physical_address) {
  78. return_ACPI_STATUS (AE_BAD_PARAMETER);
  79. }
  80. /* Make sure that we have an FACS */
  81. if (!acpi_gbl_FACS) {
  82. return_ACPI_STATUS (AE_NO_ACPI_TABLES);
  83. }
  84. /* Get the vector */
  85. if (acpi_gbl_FACS->vector_width == 32) {
  86. *physical_address = * (u32 *) acpi_gbl_FACS->firmware_waking_vector;
  87. }
  88. else {
  89. *physical_address = *acpi_gbl_FACS->firmware_waking_vector;
  90. }
  91. return_ACPI_STATUS (AE_OK);
  92. }
  93. /******************************************************************************
  94.  *
  95.  * FUNCTION:    Acpi_enter_sleep_state
  96.  *
  97.  * PARAMETERS:  Sleep_state         - Which sleep state to enter
  98.  *
  99.  * RETURN:      Status
  100.  *
  101.  * DESCRIPTION: Enter a system sleep state (see ACPI 2.0 spec p 231)
  102.  *
  103.  ******************************************************************************/
  104. acpi_status
  105. acpi_enter_sleep_state (
  106. u8                  sleep_state)
  107. {
  108. acpi_status         status;
  109. acpi_object_list    arg_list;
  110. acpi_object         arg;
  111. u8                  type_a;
  112. u8                  type_b;
  113. u16                 PM1Acontrol;
  114. u16                 PM1Bcontrol;
  115. FUNCTION_TRACE ("Acpi_enter_sleep_state");
  116. /*
  117.  * _PSW methods could be run here to enable wake-on keyboard, LAN, etc.
  118.  */
  119. status = acpi_hw_obtain_sleep_type_register_data (sleep_state, &type_a, &type_b);
  120. if (!ACPI_SUCCESS (status)) {
  121. return status;
  122. }
  123. /* run the _PTS and _GTS methods */
  124. MEMSET(&arg_list, 0, sizeof(arg_list));
  125. arg_list.count = 1;
  126. arg_list.pointer = &arg;
  127. MEMSET(&arg, 0, sizeof(arg));
  128. arg.type = ACPI_TYPE_INTEGER;
  129. arg.integer.value = sleep_state;
  130. acpi_evaluate_object (NULL, "\_PTS", &arg_list, NULL);
  131. acpi_evaluate_object (NULL, "\_GTS", &arg_list, NULL);
  132. /* clear wake status */
  133. acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_LOCK, WAK_STS, 1);
  134. disable ();
  135. acpi_hw_disable_non_wakeup_gpes();
  136. PM1Acontrol = (u16) acpi_hw_register_read (ACPI_MTX_LOCK, PM1_CONTROL);
  137. ACPI_DEBUG_PRINT ((ACPI_DB_OK, "Entering S%dn", sleep_state));
  138. /* mask off SLP_EN and SLP_TYP fields */
  139. PM1Acontrol &= ~(SLP_TYPE_X_MASK | SLP_EN_MASK);
  140. PM1Bcontrol = PM1Acontrol;
  141. /* mask in SLP_TYP */
  142. PM1Acontrol |= (type_a << acpi_hw_get_bit_shift (SLP_TYPE_X_MASK));
  143. PM1Bcontrol |= (type_b << acpi_hw_get_bit_shift (SLP_TYPE_X_MASK));
  144. /* write #1: fill in SLP_TYP data */
  145. acpi_hw_register_write (ACPI_MTX_LOCK, PM1A_CONTROL, PM1Acontrol);
  146. acpi_hw_register_write (ACPI_MTX_LOCK, PM1B_CONTROL, PM1Bcontrol);
  147. /* mask in SLP_EN */
  148. PM1Acontrol |= (1 << acpi_hw_get_bit_shift (SLP_EN_MASK));
  149. PM1Bcontrol |= (1 << acpi_hw_get_bit_shift (SLP_EN_MASK));
  150. /* flush caches */
  151. wbinvd();
  152. /* write #2: SLP_TYP + SLP_EN */
  153. acpi_hw_register_write (ACPI_MTX_LOCK, PM1A_CONTROL, PM1Acontrol);
  154. acpi_hw_register_write (ACPI_MTX_LOCK, PM1B_CONTROL, PM1Bcontrol);
  155. /*
  156.  * Wait a second, then try again. This is to get S4/5 to work on all machines.
  157.  */
  158. if (sleep_state > ACPI_STATE_S3) {
  159. acpi_os_stall(1000000);
  160. acpi_hw_register_write (ACPI_MTX_LOCK, PM1_CONTROL,
  161. (1 << acpi_hw_get_bit_shift (SLP_EN_MASK)));
  162. }
  163. /* wait until we enter sleep state */
  164. do {
  165. acpi_os_stall(10000);
  166. }
  167. while (!acpi_hw_register_bit_access (ACPI_READ, ACPI_MTX_LOCK, WAK_STS));
  168. acpi_hw_enable_non_wakeup_gpes();
  169. enable ();
  170. return_ACPI_STATUS (AE_OK);
  171. }
  172. /******************************************************************************
  173.  *
  174.  * FUNCTION:    Acpi_leave_sleep_state
  175.  *
  176.  * PARAMETERS:  Sleep_state         - Which sleep state we just exited
  177.  *
  178.  * RETURN:      Status
  179.  *
  180.  * DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep
  181.  *
  182.  ******************************************************************************/
  183. acpi_status
  184. acpi_leave_sleep_state (
  185. u8                  sleep_state)
  186. {
  187. acpi_object_list    arg_list;
  188. acpi_object         arg;
  189. FUNCTION_TRACE ("Acpi_leave_sleep_state");
  190. MEMSET (&arg_list, 0, sizeof(arg_list));
  191. arg_list.count = 1;
  192. arg_list.pointer = &arg;
  193. MEMSET (&arg, 0, sizeof(arg));
  194. arg.type = ACPI_TYPE_INTEGER;
  195. arg.integer.value = sleep_state;
  196. acpi_evaluate_object (NULL, "\_BFS", &arg_list, NULL);
  197. acpi_evaluate_object (NULL, "\_WAK", &arg_list, NULL);
  198. /* _WAK returns stuff - do we want to look at it? */
  199. acpi_hw_enable_non_wakeup_gpes();
  200. return_ACPI_STATUS (AE_OK);
  201. }