hwacpi.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:8k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /******************************************************************************
  2.  *
  3.  * Module Name: hwacpi - ACPI Hardware Initialization/Mode Interface
  4.  *              $Revision: 46 $
  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 "achware.h"
  26. #define _COMPONENT          ACPI_HARDWARE
  27.  MODULE_NAME         ("hwacpi")
  28. /******************************************************************************
  29.  *
  30.  * FUNCTION:    Acpi_hw_initialize
  31.  *
  32.  * PARAMETERS:  None
  33.  *
  34.  * RETURN:      Status
  35.  *
  36.  * DESCRIPTION: Initialize and validate various ACPI registers
  37.  *
  38.  ******************************************************************************/
  39. acpi_status
  40. acpi_hw_initialize (
  41. void)
  42. {
  43. acpi_status             status = AE_OK;
  44. u32                     index;
  45. FUNCTION_TRACE ("Hw_initialize");
  46. /* We must have the ACPI tables by the time we get here */
  47. if (!acpi_gbl_FADT) {
  48. acpi_gbl_restore_acpi_chipset = FALSE;
  49. ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No FADT!n"));
  50. return_ACPI_STATUS (AE_NO_ACPI_TABLES);
  51. }
  52. /* Identify current ACPI/legacy mode   */
  53. switch (acpi_gbl_system_flags & SYS_MODES_MASK) {
  54. case (SYS_MODE_ACPI):
  55. acpi_gbl_original_mode = SYS_MODE_ACPI;
  56. ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "System supports ACPI mode only.n"));
  57. break;
  58. case (SYS_MODE_LEGACY):
  59. acpi_gbl_original_mode = SYS_MODE_LEGACY;
  60. ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
  61. "Tables loaded from buffer, hardware assumed to support LEGACY mode only.n"));
  62. break;
  63. case (SYS_MODE_ACPI | SYS_MODE_LEGACY):
  64. if (acpi_hw_get_mode () == SYS_MODE_ACPI) {
  65. acpi_gbl_original_mode = SYS_MODE_ACPI;
  66. }
  67. else {
  68. acpi_gbl_original_mode = SYS_MODE_LEGACY;
  69. }
  70. ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
  71. "System supports both ACPI and LEGACY modes.n"));
  72. ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
  73. "System is currently in %s mode.n",
  74. (acpi_gbl_original_mode == SYS_MODE_ACPI) ? "ACPI" : "LEGACY"));
  75. break;
  76. }
  77. if (acpi_gbl_system_flags & SYS_MODE_ACPI) {
  78. /* Target system supports ACPI mode */
  79. /*
  80.  * The purpose of this code is to save the initial state
  81.  * of the ACPI event enable registers. An exit function will be
  82.  * registered which will restore this state when the application
  83.  * exits. The exit function will also clear all of the ACPI event
  84.  * status bits prior to restoring the original mode.
  85.  *
  86.  * The location of the PM1a_evt_blk enable registers is defined as the
  87.  * base of PM1a_evt_blk + DIV_2(PM1a_evt_blk_length). Since the spec further
  88.  * fully defines the PM1a_evt_blk to be a total of 4 bytes, the offset
  89.  * for the enable registers is always 2 from the base. It is hard
  90.  * coded here. If this changes in the spec, this code will need to
  91.  * be modified. The PM1b_evt_blk behaves as expected.
  92.  */
  93. acpi_gbl_pm1_enable_register_save = (u16) acpi_hw_register_read (
  94.    ACPI_MTX_LOCK, PM1_EN);
  95. /*
  96.  * The GPEs behave similarly, except that the length of the register
  97.  * block is not fixed, so the buffer must be allocated with malloc
  98.  */
  99. if (ACPI_VALID_ADDRESS (acpi_gbl_FADT->Xgpe0blk.address) &&
  100. acpi_gbl_FADT->gpe0blk_len) {
  101. /* GPE0 specified in FADT  */
  102. acpi_gbl_gpe0enable_register_save = ACPI_MEM_ALLOCATE (
  103.    DIV_2 (acpi_gbl_FADT->gpe0blk_len));
  104. if (!acpi_gbl_gpe0enable_register_save) {
  105. return_ACPI_STATUS (AE_NO_MEMORY);
  106. }
  107. /* Save state of GPE0 enable bits */
  108. for (index = 0; index < DIV_2 (acpi_gbl_FADT->gpe0blk_len); index++) {
  109. acpi_gbl_gpe0enable_register_save[index] =
  110. (u8) acpi_hw_register_read (ACPI_MTX_LOCK, GPE0_EN_BLOCK | index);
  111. }
  112. }
  113. else {
  114. acpi_gbl_gpe0enable_register_save = NULL;
  115. }
  116. if (ACPI_VALID_ADDRESS (acpi_gbl_FADT->Xgpe1_blk.address) &&
  117. acpi_gbl_FADT->gpe1_blk_len) {
  118. /* GPE1 defined */
  119. acpi_gbl_gpe1_enable_register_save = ACPI_MEM_ALLOCATE (
  120.    DIV_2 (acpi_gbl_FADT->gpe1_blk_len));
  121. if (!acpi_gbl_gpe1_enable_register_save) {
  122. return_ACPI_STATUS (AE_NO_MEMORY);
  123. }
  124. /* save state of GPE1 enable bits */
  125. for (index = 0; index < DIV_2 (acpi_gbl_FADT->gpe1_blk_len); index++) {
  126. acpi_gbl_gpe1_enable_register_save[index] =
  127. (u8) acpi_hw_register_read (ACPI_MTX_LOCK, GPE1_EN_BLOCK | index);
  128. }
  129. }
  130. else {
  131. acpi_gbl_gpe1_enable_register_save = NULL;
  132. }
  133. }
  134. return_ACPI_STATUS (status);
  135. }
  136. /******************************************************************************
  137.  *
  138.  * FUNCTION:    Acpi_hw_set_mode
  139.  *
  140.  * PARAMETERS:  Mode            - SYS_MODE_ACPI or SYS_MODE_LEGACY
  141.  *
  142.  * RETURN:      Status
  143.  *
  144.  * DESCRIPTION: Transitions the system into the requested mode or does nothing
  145.  *              if the system is already in that mode.
  146.  *
  147.  ******************************************************************************/
  148. acpi_status
  149. acpi_hw_set_mode (
  150. u32                     mode)
  151. {
  152. acpi_status             status = AE_NO_HARDWARE_RESPONSE;
  153. FUNCTION_TRACE ("Hw_set_mode");
  154. if (mode == SYS_MODE_ACPI) {
  155. /* BIOS should have disabled ALL fixed and GP events */
  156. acpi_os_write_port (acpi_gbl_FADT->smi_cmd, acpi_gbl_FADT->acpi_enable, 8);
  157. ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Attempting to enable ACPI moden"));
  158. }
  159. else if (mode == SYS_MODE_LEGACY) {
  160. /*
  161.  * BIOS should clear all fixed status bits and restore fixed event
  162.  * enable bits to default
  163.  */
  164. acpi_os_write_port (acpi_gbl_FADT->smi_cmd, acpi_gbl_FADT->acpi_disable, 8);
  165. ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
  166.  "Attempting to enable Legacy (non-ACPI) moden"));
  167. }
  168. /* Give the platform some time to react */
  169. acpi_os_stall (20000);
  170. if (acpi_hw_get_mode () == mode) {
  171. ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Mode %X successfully enabledn", mode));
  172. status = AE_OK;
  173. }
  174. return_ACPI_STATUS (status);
  175. }
  176. /******************************************************************************
  177.  *
  178.  * FUNCTION:    Acpi_hw_get_mode
  179.  *
  180.  * PARAMETERS:  none
  181.  *
  182.  * RETURN:      SYS_MODE_ACPI or SYS_MODE_LEGACY
  183.  *
  184.  * DESCRIPTION: Return current operating state of system.  Determined by
  185.  *              querying the SCI_EN bit.
  186.  *
  187.  ******************************************************************************/
  188. u32
  189. acpi_hw_get_mode (void)
  190. {
  191. FUNCTION_TRACE ("Hw_get_mode");
  192. if (acpi_hw_register_bit_access (ACPI_READ, ACPI_MTX_LOCK, SCI_EN)) {
  193. return_VALUE (SYS_MODE_ACPI);
  194. }
  195. else {
  196. return_VALUE (SYS_MODE_LEGACY);
  197. }
  198. }
  199. /******************************************************************************
  200.  *
  201.  * FUNCTION:    Acpi_hw_get_mode_capabilities
  202.  *
  203.  * PARAMETERS:  none
  204.  *
  205.  * RETURN:      logical OR of SYS_MODE_ACPI and SYS_MODE_LEGACY determined at initial
  206.  *              system state.
  207.  *
  208.  * DESCRIPTION: Returns capablities of system
  209.  *
  210.  ******************************************************************************/
  211. u32
  212. acpi_hw_get_mode_capabilities (void)
  213. {
  214. FUNCTION_TRACE ("Hw_get_mode_capabilities");
  215. if (!(acpi_gbl_system_flags & SYS_MODES_MASK)) {
  216. if (acpi_hw_get_mode () == SYS_MODE_LEGACY) {
  217. /*
  218.  * Assume that if this call is being made, Acpi_init has been called
  219.  * and ACPI support has been established by the presence of the
  220.  * tables.  Therefore since we're in SYS_MODE_LEGACY, the system
  221.  * must support both modes
  222.  */
  223. acpi_gbl_system_flags |= (SYS_MODE_ACPI | SYS_MODE_LEGACY);
  224. }
  225. else {
  226. /* TBD: [Investigate] !!! this may be unsafe... */
  227. /*
  228.  * system is is ACPI mode, so try to switch back to LEGACY to see if
  229.  * it is supported
  230.  */
  231. acpi_hw_set_mode (SYS_MODE_LEGACY);
  232. if (acpi_hw_get_mode () == SYS_MODE_LEGACY) {
  233. /* Now in SYS_MODE_LEGACY, so both are supported */
  234. acpi_gbl_system_flags |= (SYS_MODE_ACPI | SYS_MODE_LEGACY);
  235. acpi_hw_set_mode (SYS_MODE_ACPI);
  236. }
  237. else {
  238. /* Still in SYS_MODE_ACPI so this must be an ACPI only system */
  239. acpi_gbl_system_flags |= SYS_MODE_ACPI;
  240. }
  241. }
  242. }
  243. return_VALUE (acpi_gbl_system_flags & SYS_MODES_MASK);
  244. }