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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*******************************************************************************
  2.  *
  3.  * Module Name: hwregs - Read/write access functions for the various ACPI
  4.  *                       control and status registers.
  5.  *              $Revision: 110 $
  6.  *
  7.  ******************************************************************************/
  8. /*
  9.  *  Copyright (C) 2000, 2001 R. Byron Moore
  10.  *
  11.  *  This program is free software; you can redistribute it and/or modify
  12.  *  it under the terms of the GNU General Public License as published by
  13.  *  the Free Software Foundation; either version 2 of the License, or
  14.  *  (at your option) any later version.
  15.  *
  16.  *  This program is distributed in the hope that it will be useful,
  17.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  18.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19.  *  GNU General Public License for more details.
  20.  *
  21.  *  You should have received a copy of the GNU General Public License
  22.  *  along with this program; if not, write to the Free Software
  23.  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  24.  */
  25. #include "acpi.h"
  26. #include "achware.h"
  27. #include "acnamesp.h"
  28. #define _COMPONENT          ACPI_HARDWARE
  29.  MODULE_NAME         ("hwregs")
  30. /*******************************************************************************
  31.  *
  32.  * FUNCTION:    Acpi_hw_get_bit_shift
  33.  *
  34.  * PARAMETERS:  Mask            - Input mask to determine bit shift from.
  35.  *                                Must have at least 1 bit set.
  36.  *
  37.  * RETURN:      Bit location of the lsb of the mask
  38.  *
  39.  * DESCRIPTION: Returns the bit number for the low order bit that's set.
  40.  *
  41.  ******************************************************************************/
  42. u32
  43. acpi_hw_get_bit_shift (
  44. u32                     mask)
  45. {
  46. u32                     shift;
  47. FUNCTION_TRACE ("Hw_get_bit_shift");
  48. for (shift = 0; ((mask >> shift) & 1) == 0; shift++) { ; }
  49. return_VALUE (shift);
  50. }
  51. /*******************************************************************************
  52.  *
  53.  * FUNCTION:    Acpi_hw_clear_acpi_status
  54.  *
  55.  * PARAMETERS:  none
  56.  *
  57.  * RETURN:      none
  58.  *
  59.  * DESCRIPTION: Clears all fixed and general purpose status bits
  60.  *
  61.  ******************************************************************************/
  62. void
  63. acpi_hw_clear_acpi_status (void)
  64. {
  65. u16                     gpe_length;
  66. u16                     index;
  67. FUNCTION_TRACE ("Hw_clear_acpi_status");
  68. ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %04X to %04Xn",
  69. ALL_FIXED_STS_BITS,
  70. (u16) ACPI_GET_ADDRESS (acpi_gbl_FADT->Xpm1a_evt_blk.address)));
  71. acpi_ut_acquire_mutex (ACPI_MTX_HARDWARE);
  72. acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, PM1_STS, ALL_FIXED_STS_BITS);
  73. if (ACPI_VALID_ADDRESS (acpi_gbl_FADT->Xpm1b_evt_blk.address)) {
  74. acpi_os_write_port ((ACPI_IO_ADDRESS)
  75. ACPI_GET_ADDRESS (acpi_gbl_FADT->Xpm1b_evt_blk.address),
  76. ALL_FIXED_STS_BITS, 16);
  77. }
  78. /* now clear the GPE Bits */
  79. if (acpi_gbl_FADT->gpe0blk_len) {
  80. gpe_length = (u16) DIV_2 (acpi_gbl_FADT->gpe0blk_len);
  81. for (index = 0; index < gpe_length; index++) {
  82. acpi_os_write_port ((ACPI_IO_ADDRESS) (
  83. ACPI_GET_ADDRESS (acpi_gbl_FADT->Xgpe0blk.address) + index),
  84. 0xFF, 8);
  85. }
  86. }
  87. if (acpi_gbl_FADT->gpe1_blk_len) {
  88. gpe_length = (u16) DIV_2 (acpi_gbl_FADT->gpe1_blk_len);
  89. for (index = 0; index < gpe_length; index++) {
  90. acpi_os_write_port ((ACPI_IO_ADDRESS) (
  91. ACPI_GET_ADDRESS (acpi_gbl_FADT->Xgpe1_blk.address) + index),
  92. 0xFF, 8);
  93. }
  94. }
  95. acpi_ut_release_mutex (ACPI_MTX_HARDWARE);
  96. return_VOID;
  97. }
  98. /*******************************************************************************
  99.  *
  100.  * FUNCTION:    Acpi_hw_obtain_sleep_type_register_data
  101.  *
  102.  * PARAMETERS:  Sleep_state       - Numeric state requested
  103.  *              *Slp_Typ_a         - Pointer to byte to receive SLP_TYPa value
  104.  *              *Slp_Typ_b         - Pointer to byte to receive SLP_TYPb value
  105.  *
  106.  * RETURN:      Status - ACPI status
  107.  *
  108.  * DESCRIPTION: Acpi_hw_obtain_sleep_type_register_data() obtains the SLP_TYP and
  109.  *              SLP_TYPb values for the sleep state requested.
  110.  *
  111.  ******************************************************************************/
  112. acpi_status
  113. acpi_hw_obtain_sleep_type_register_data (
  114. u8                      sleep_state,
  115. u8                      *slp_typ_a,
  116. u8                      *slp_typ_b)
  117. {
  118. acpi_status             status = AE_OK;
  119. acpi_operand_object     *obj_desc;
  120. FUNCTION_TRACE ("Hw_obtain_sleep_type_register_data");
  121. /*
  122.  *  Validate parameters
  123.  */
  124. if ((sleep_state > ACPI_S_STATES_MAX) ||
  125. !slp_typ_a || !slp_typ_b) {
  126. return_ACPI_STATUS (AE_BAD_PARAMETER);
  127. }
  128. /*
  129.  *  Acpi_evaluate the namespace object containing the values for this state
  130.  */
  131. status = acpi_ns_evaluate_by_name ((NATIVE_CHAR *) acpi_gbl_db_sleep_states[sleep_state],
  132.   NULL, &obj_desc);
  133. if (ACPI_FAILURE (status)) {
  134. return_ACPI_STATUS (status);
  135. }
  136. if (!obj_desc) {
  137. REPORT_ERROR (("Missing Sleep State objectn"));
  138. return_ACPI_STATUS (AE_NOT_EXIST);
  139. }
  140. /*
  141.  *  We got something, now ensure it is correct.  The object must
  142.  *  be a package and must have at least 2 numeric values as the
  143.  *  two elements
  144.  */
  145. /* Even though Acpi_evaluate_object resolves package references,
  146.  * Ns_evaluate dpesn't. So, we do it here.
  147.  */
  148. status = acpi_ut_resolve_package_references(obj_desc);
  149. if (obj_desc->package.count < 2) {
  150. /* Must have at least two elements */
  151. REPORT_ERROR (("Sleep State package does not have at least two elementsn"));
  152. status = AE_ERROR;
  153. }
  154. else if (((obj_desc->package.elements[0])->common.type !=
  155.  ACPI_TYPE_INTEGER) ||
  156.  ((obj_desc->package.elements[1])->common.type !=
  157. ACPI_TYPE_INTEGER)) {
  158. /* Must have two  */
  159. REPORT_ERROR (("Sleep State package elements are not both of type Numbern"));
  160. status = AE_ERROR;
  161. }
  162. else {
  163. /*
  164.  *  Valid _Sx_ package size, type, and value
  165.  */
  166. *slp_typ_a = (u8) (obj_desc->package.elements[0])->integer.value;
  167. *slp_typ_b = (u8) (obj_desc->package.elements[1])->integer.value;
  168. }
  169. if (ACPI_FAILURE (status)) {
  170. ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Bad Sleep object %p type %Xn",
  171. obj_desc, obj_desc->common.type));
  172. }
  173. acpi_ut_remove_reference (obj_desc);
  174. return_ACPI_STATUS (status);
  175. }
  176. /*******************************************************************************
  177.  *
  178.  * FUNCTION:    Acpi_hw_register_bit_access
  179.  *
  180.  * PARAMETERS:  Read_write      - Either ACPI_READ or ACPI_WRITE.
  181.  *              Use_lock        - Lock the hardware
  182.  *              Register_id     - index of ACPI Register to access
  183.  *              Value           - (only used on write) value to write to the
  184.  *                                Register.  Shifted all the way right.
  185.  *
  186.  * RETURN:      Value written to or read from specified Register.  This value
  187.  *              is shifted all the way right.
  188.  *
  189.  * DESCRIPTION: Generic ACPI Register read/write function.
  190.  *
  191.  ******************************************************************************/
  192. u32
  193. acpi_hw_register_bit_access (
  194. NATIVE_UINT             read_write,
  195. u8                      use_lock,
  196. u32                     register_id,
  197. ...)                    /* Value (only used on write) */
  198. {
  199. u32                     register_value = 0;
  200. u32                     mask = 0;
  201. u32                     value = 0;
  202. va_list                 marker;
  203. FUNCTION_TRACE ("Hw_register_bit_access");
  204. if (read_write == ACPI_WRITE) {
  205. va_start (marker, register_id);
  206. value = va_arg (marker, u32);
  207. va_end (marker);
  208. }
  209. if (ACPI_MTX_LOCK == use_lock) {
  210. acpi_ut_acquire_mutex (ACPI_MTX_HARDWARE);
  211. }
  212. /*
  213.  * Decode the Register ID
  214.  * Register id = Register block id | bit id
  215.  *
  216.  * Check bit id to fine locate Register offset.
  217.  * Check Mask to determine Register offset, and then read-write.
  218.  */
  219. switch (REGISTER_BLOCK_ID (register_id)) {
  220. case PM1_STS:
  221. switch (register_id) {
  222. case TMR_STS:
  223. mask = TMR_STS_MASK;
  224. break;
  225. case BM_STS:
  226. mask = BM_STS_MASK;
  227. break;
  228. case GBL_STS:
  229. mask = GBL_STS_MASK;
  230. break;
  231. case PWRBTN_STS:
  232. mask = PWRBTN_STS_MASK;
  233. break;
  234. case SLPBTN_STS:
  235. mask = SLPBTN_STS_MASK;
  236. break;
  237. case RTC_STS:
  238. mask = RTC_STS_MASK;
  239. break;
  240. case WAK_STS:
  241. mask = WAK_STS_MASK;
  242. break;
  243. default:
  244. mask = 0;
  245. break;
  246. }
  247. register_value = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, PM1_STS);
  248. if (read_write == ACPI_WRITE) {
  249. /*
  250.  * Status Registers are different from the rest.  Clear by
  251.  * writing 1, writing 0 has no effect.  So, the only relevent
  252.  * information is the single bit we're interested in, all
  253.  * others should be written as 0 so they will be left
  254.  * unchanged
  255.  */
  256. value <<= acpi_hw_get_bit_shift (mask);
  257. value &= mask;
  258. if (value) {
  259. acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, PM1_STS,
  260. (u16) value);
  261. register_value = 0;
  262. }
  263. }
  264. break;
  265. case PM1_EN:
  266. switch (register_id) {
  267. case TMR_EN:
  268. mask = TMR_EN_MASK;
  269. break;
  270. case GBL_EN:
  271. mask = GBL_EN_MASK;
  272. break;
  273. case PWRBTN_EN:
  274. mask = PWRBTN_EN_MASK;
  275. break;
  276. case SLPBTN_EN:
  277. mask = SLPBTN_EN_MASK;
  278. break;
  279. case RTC_EN:
  280. mask = RTC_EN_MASK;
  281. break;
  282. default:
  283. mask = 0;
  284. break;
  285. }
  286. register_value = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, PM1_EN);
  287. if (read_write == ACPI_WRITE) {
  288. register_value &= ~mask;
  289. value          <<= acpi_hw_get_bit_shift (mask);
  290. value          &= mask;
  291. register_value |= value;
  292. acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, PM1_EN, (u16) register_value);
  293. }
  294. break;
  295. case PM1_CONTROL:
  296. switch (register_id) {
  297. case SCI_EN:
  298. mask = SCI_EN_MASK;
  299. break;
  300. case BM_RLD:
  301. mask = BM_RLD_MASK;
  302. break;
  303. case GBL_RLS:
  304. mask = GBL_RLS_MASK;
  305. break;
  306. case SLP_TYPE_A:
  307. case SLP_TYPE_B:
  308. mask = SLP_TYPE_X_MASK;
  309. break;
  310. case SLP_EN:
  311. mask = SLP_EN_MASK;
  312. break;
  313. default:
  314. mask = 0;
  315. break;
  316. }
  317. /*
  318.  * Read the PM1 Control register.
  319.  * Note that at this level, the fact that there are actually TWO
  320.  * registers (A and B) and that B may not exist, are abstracted.
  321.  */
  322. register_value = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, PM1_CONTROL);
  323. ACPI_DEBUG_PRINT ((ACPI_DB_IO, "PM1 control: Read %Xn", register_value));
  324. if (read_write == ACPI_WRITE) {
  325. register_value &= ~mask;
  326. value          <<= acpi_hw_get_bit_shift (mask);
  327. value          &= mask;
  328. register_value |= value;
  329. /*
  330.  * SLP_TYPE_x Registers are written differently
  331.  * than any other control Registers with
  332.  * respect to A and B Registers.  The value
  333.  * for A may be different than the value for B
  334.  *
  335.  * Therefore, pass the Register_id, not just generic PM1_CONTROL,
  336.  * because we need to do different things. Yuck.
  337.  */
  338. acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, register_id,
  339. (u16) register_value);
  340. }
  341. break;
  342. case PM2_CONTROL:
  343. switch (register_id) {
  344. case ARB_DIS:
  345. mask = ARB_DIS_MASK;
  346. break;
  347. default:
  348. mask = 0;
  349. break;
  350. }
  351. register_value = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, PM2_CONTROL);
  352. ACPI_DEBUG_PRINT ((ACPI_DB_IO, "PM2 control: Read %X from %8.8X%8.8Xn",
  353. register_value, HIDWORD(acpi_gbl_FADT->Xpm2_cnt_blk.address),
  354. LODWORD(acpi_gbl_FADT->Xpm2_cnt_blk.address)));
  355. if (read_write == ACPI_WRITE) {
  356. register_value &= ~mask;
  357. value          <<= acpi_hw_get_bit_shift (mask);
  358. value          &= mask;
  359. register_value |= value;
  360. ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %04X to %8.8X%8.8Xn",
  361. register_value,
  362. HIDWORD(acpi_gbl_FADT->Xpm2_cnt_blk.address),
  363. LODWORD(acpi_gbl_FADT->Xpm2_cnt_blk.address)));
  364. acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK,
  365.    PM2_CONTROL, (u8) (register_value));
  366. }
  367. break;
  368. case PM_TIMER:
  369. mask = TMR_VAL_MASK;
  370. register_value = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK,
  371.  PM_TIMER);
  372. ACPI_DEBUG_PRINT ((ACPI_DB_IO, "PM_TIMER: Read %X from %8.8X%8.8Xn",
  373. register_value,
  374. HIDWORD(acpi_gbl_FADT->Xpm_tmr_blk.address),
  375. LODWORD(acpi_gbl_FADT->Xpm_tmr_blk.address)));
  376. break;
  377. case GPE1_EN_BLOCK:
  378. case GPE1_STS_BLOCK:
  379. case GPE0_EN_BLOCK:
  380. case GPE0_STS_BLOCK:
  381. /* Determine the bit to be accessed
  382.  *
  383.  *  (u32) Register_id:
  384.  *      31      24       16       8        0
  385.  *      +--------+--------+--------+--------+
  386.  *      |  gpe_block_id   |  gpe_bit_number |
  387.  *      +--------+--------+--------+--------+
  388.  *
  389.  *     gpe_block_id is one of GPE[01]_EN_BLOCK and GPE[01]_STS_BLOCK
  390.  *     gpe_bit_number is relative from the gpe_block (0x00~0xFF)
  391.  */
  392. mask = REGISTER_BIT_ID(register_id); /* gpe_bit_number */
  393. register_id = REGISTER_BLOCK_ID(register_id) | (mask >> 3);
  394. mask = acpi_gbl_decode_to8bit [mask % 8];
  395. /*
  396.  * The base address of the GPE 0 Register Block
  397.  * Plus 1/2 the length of the GPE 0 Register Block
  398.  * The enable Register is the Register following the Status Register
  399.  * and each Register is defined as 1/2 of the total Register Block
  400.  */
  401. /*
  402.  * This sets the bit within Enable_bit that needs to be written to
  403.  * the Register indicated in Mask to a 1, all others are 0
  404.  */
  405. /* Now get the current Enable Bits in the selected Reg */
  406. register_value = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, register_id);
  407. ACPI_DEBUG_PRINT ((ACPI_DB_IO, "GPE Enable bits: Read %X from %Xn",
  408. register_value, register_id));
  409. if (read_write == ACPI_WRITE) {
  410. register_value &= ~mask;
  411. value          <<= acpi_hw_get_bit_shift (mask);
  412. value          &= mask;
  413. register_value |= value;
  414. /*
  415.  * This write will put the Action state into the General Purpose
  416.  * Enable Register indexed by the value in Mask
  417.  */
  418. ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %04X to %04Xn",
  419. register_value, register_id));
  420. acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, register_id,
  421. (u8) register_value);
  422. register_value = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK,
  423.    register_id);
  424. }
  425. break;
  426. case SMI_CMD_BLOCK:
  427. case PROCESSOR_BLOCK:
  428. /* Not used by any callers at this time - therefore, not implemented */
  429. default:
  430. mask = 0;
  431. break;
  432. }
  433. if (ACPI_MTX_LOCK == use_lock) {
  434. acpi_ut_release_mutex (ACPI_MTX_HARDWARE);
  435. }
  436. register_value &= mask;
  437. register_value >>= acpi_hw_get_bit_shift (mask);
  438. ACPI_DEBUG_PRINT ((ACPI_DB_IO, "Register I/O: returning %Xn", register_value));
  439. return_VALUE (register_value);
  440. }
  441. /******************************************************************************
  442.  *
  443.  * FUNCTION:    Acpi_hw_register_read
  444.  *
  445.  * PARAMETERS:  Use_lock               - Mutex hw access.
  446.  *              Register_id            - Register_iD + Offset.
  447.  *
  448.  * RETURN:      Value read or written.
  449.  *
  450.  * DESCRIPTION: Acpi register read function.  Registers are read at the
  451.  *              given offset.
  452.  *
  453.  ******************************************************************************/
  454. u32
  455. acpi_hw_register_read (
  456. u8                      use_lock,
  457. u32                     register_id)
  458. {
  459. u32                     value = 0;
  460. u32                     bank_offset;
  461. FUNCTION_TRACE ("Hw_register_read");
  462. if (ACPI_MTX_LOCK == use_lock) {
  463. acpi_ut_acquire_mutex (ACPI_MTX_HARDWARE);
  464. }
  465. switch (REGISTER_BLOCK_ID(register_id)) {
  466. case PM1_STS: /* 16-bit access */
  467. value =  acpi_hw_low_level_read (16, &acpi_gbl_FADT->Xpm1a_evt_blk, 0);
  468. value |= acpi_hw_low_level_read (16, &acpi_gbl_FADT->Xpm1b_evt_blk, 0);
  469. break;
  470. case PM1_EN: /* 16-bit access*/
  471. bank_offset = DIV_2 (acpi_gbl_FADT->pm1_evt_len);
  472. value =  acpi_hw_low_level_read (16, &acpi_gbl_FADT->Xpm1a_evt_blk, bank_offset);
  473. value |= acpi_hw_low_level_read (16, &acpi_gbl_FADT->Xpm1b_evt_blk, bank_offset);
  474. break;
  475. case PM1_CONTROL: /* 16-bit access */
  476. value =  acpi_hw_low_level_read (16, &acpi_gbl_FADT->Xpm1a_cnt_blk, 0);
  477. value |= acpi_hw_low_level_read (16, &acpi_gbl_FADT->Xpm1b_cnt_blk, 0);
  478. break;
  479. case PM2_CONTROL: /* 8-bit access */
  480. value =  acpi_hw_low_level_read (8, &acpi_gbl_FADT->Xpm2_cnt_blk, 0);
  481. break;
  482. case PM_TIMER: /* 32-bit access */
  483. value =  acpi_hw_low_level_read (32, &acpi_gbl_FADT->Xpm_tmr_blk, 0);
  484. break;
  485. /*
  486.  * For the GPE? Blocks, the lower word of Register_id contains the
  487.  * byte offset for which to read, as each part of each block may be
  488.  * several bytes long.
  489.  */
  490. case GPE0_STS_BLOCK: /* 8-bit access */
  491. bank_offset = REGISTER_BIT_ID(register_id);
  492. value = acpi_hw_low_level_read (8, &acpi_gbl_FADT->Xgpe0blk, bank_offset);
  493. break;
  494. case GPE0_EN_BLOCK: /* 8-bit access */
  495. bank_offset = DIV_2 (acpi_gbl_FADT->gpe0blk_len) + REGISTER_BIT_ID(register_id);
  496. value = acpi_hw_low_level_read (8, &acpi_gbl_FADT->Xgpe0blk, bank_offset);
  497. break;
  498. case GPE1_STS_BLOCK: /* 8-bit access */
  499. bank_offset = REGISTER_BIT_ID(register_id);
  500. value = acpi_hw_low_level_read (8, &acpi_gbl_FADT->Xgpe1_blk, bank_offset);
  501. break;
  502. case GPE1_EN_BLOCK: /* 8-bit access */
  503. bank_offset = DIV_2 (acpi_gbl_FADT->gpe1_blk_len) + REGISTER_BIT_ID(register_id);
  504. value = acpi_hw_low_level_read (8, &acpi_gbl_FADT->Xgpe1_blk, bank_offset);
  505. break;
  506. case SMI_CMD_BLOCK: /* 8bit */
  507. acpi_os_read_port (acpi_gbl_FADT->smi_cmd, &value, 8);
  508. break;
  509. default:
  510. /* Value will be returned as 0 */
  511. break;
  512. }
  513. if (ACPI_MTX_LOCK == use_lock) {
  514. acpi_ut_release_mutex (ACPI_MTX_HARDWARE);
  515. }
  516. return_VALUE (value);
  517. }
  518. /******************************************************************************
  519.  *
  520.  * FUNCTION:    Acpi_hw_register_write
  521.  *
  522.  * PARAMETERS:  Use_lock               - Mutex hw access.
  523.  *              Register_id            - Register_iD + Offset.
  524.  *
  525.  * RETURN:      Value read or written.
  526.  *
  527.  * DESCRIPTION: Acpi register Write function.  Registers are written at the
  528.  *              given offset.
  529.  *
  530.  ******************************************************************************/
  531. void
  532. acpi_hw_register_write (
  533. u8                      use_lock,
  534. u32                     register_id,
  535. u32                     value)
  536. {
  537. u32                     bank_offset;
  538. FUNCTION_TRACE ("Hw_register_write");
  539. if (ACPI_MTX_LOCK == use_lock) {
  540. acpi_ut_acquire_mutex (ACPI_MTX_HARDWARE);
  541. }
  542. switch (REGISTER_BLOCK_ID (register_id)) {
  543. case PM1_STS: /* 16-bit access */
  544. acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1a_evt_blk, 0);
  545. acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1b_evt_blk, 0);
  546. break;
  547. case PM1_EN: /* 16-bit access*/
  548. bank_offset = DIV_2 (acpi_gbl_FADT->pm1_evt_len);
  549. acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1a_evt_blk, bank_offset);
  550. acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1b_evt_blk, bank_offset);
  551. break;
  552. case PM1_CONTROL: /* 16-bit access */
  553. acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1a_cnt_blk, 0);
  554. acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1b_cnt_blk, 0);
  555. break;
  556. case PM1A_CONTROL: /* 16-bit access */
  557. acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1a_cnt_blk, 0);
  558. break;
  559. case PM1B_CONTROL: /* 16-bit access */
  560. acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1b_cnt_blk, 0);
  561. break;
  562. case PM2_CONTROL: /* 8-bit access */
  563. acpi_hw_low_level_write (8, value, &acpi_gbl_FADT->Xpm2_cnt_blk, 0);
  564. break;
  565. case PM_TIMER: /* 32-bit access */
  566. acpi_hw_low_level_write (32, value, &acpi_gbl_FADT->Xpm_tmr_blk, 0);
  567. break;
  568. case GPE0_STS_BLOCK: /* 8-bit access */
  569. bank_offset = REGISTER_BIT_ID(register_id);
  570. acpi_hw_low_level_write (8, value, &acpi_gbl_FADT->Xgpe0blk, bank_offset);
  571. break;
  572. case GPE0_EN_BLOCK: /* 8-bit access */
  573. bank_offset = DIV_2 (acpi_gbl_FADT->gpe0blk_len) + REGISTER_BIT_ID(register_id);
  574. acpi_hw_low_level_write (8, value, &acpi_gbl_FADT->Xgpe0blk, bank_offset);
  575. break;
  576. case GPE1_STS_BLOCK: /* 8-bit access */
  577. bank_offset = REGISTER_BIT_ID(register_id);
  578. acpi_hw_low_level_write (8, value, &acpi_gbl_FADT->Xgpe1_blk, bank_offset);
  579. break;
  580. case GPE1_EN_BLOCK: /* 8-bit access */
  581. bank_offset = DIV_2 (acpi_gbl_FADT->gpe1_blk_len) + REGISTER_BIT_ID(register_id);
  582. acpi_hw_low_level_write (8, value, &acpi_gbl_FADT->Xgpe1_blk, bank_offset);
  583. break;
  584. case SMI_CMD_BLOCK: /* 8bit */
  585. /* For 2.0, SMI_CMD is always in IO space */
  586. /* TBD: what about 1.0? 0.71? */
  587. acpi_os_write_port (acpi_gbl_FADT->smi_cmd, value, 8);
  588. break;
  589. default:
  590. value = 0;
  591. break;
  592. }
  593. if (ACPI_MTX_LOCK == use_lock) {
  594. acpi_ut_release_mutex (ACPI_MTX_HARDWARE);
  595. }
  596. return_VOID;
  597. }
  598. /******************************************************************************
  599.  *
  600.  * FUNCTION:    Acpi_hw_low_level_read
  601.  *
  602.  * PARAMETERS:  Register            - GAS register structure
  603.  *              Offset              - Offset from the base address in the GAS
  604.  *              Width               - 8, 16, or 32
  605.  *
  606.  * RETURN:      Value read
  607.  *
  608.  * DESCRIPTION: Read from either memory, IO, or PCI config space.
  609.  *
  610.  ******************************************************************************/
  611. u32
  612. acpi_hw_low_level_read (
  613. u32                     width,
  614. acpi_generic_address    *reg,
  615. u32                     offset)
  616. {
  617. u32                     value = 0;
  618. ACPI_PHYSICAL_ADDRESS   mem_address;
  619. ACPI_IO_ADDRESS         io_address;
  620. acpi_pci_id             pci_id;
  621. u16                     pci_register;
  622. FUNCTION_ENTRY ();
  623. /*
  624.  * Must have a valid pointer to a GAS structure, and
  625.  * a non-zero address within
  626.  */
  627. if ((!reg) ||
  628. (!ACPI_VALID_ADDRESS (reg->address))) {
  629. return 0;
  630. }
  631. /*
  632.  * Three address spaces supported:
  633.  * Memory, Io, or PCI config.
  634.  */
  635. switch (reg->address_space_id) {
  636. case ACPI_ADR_SPACE_SYSTEM_MEMORY:
  637. mem_address = (ACPI_PHYSICAL_ADDRESS) (ACPI_GET_ADDRESS (reg->address) + offset);
  638. acpi_os_read_memory (mem_address, &value, width);
  639. break;
  640. case ACPI_ADR_SPACE_SYSTEM_IO:
  641. io_address = (ACPI_IO_ADDRESS) (ACPI_GET_ADDRESS (reg->address) + offset);
  642. acpi_os_read_port (io_address, &value, width);
  643. break;
  644. case ACPI_ADR_SPACE_PCI_CONFIG:
  645. pci_id.segment = 0;
  646. pci_id.bus     = 0;
  647. pci_id.device  = ACPI_PCI_DEVICE (ACPI_GET_ADDRESS (reg->address));
  648. pci_id.function = ACPI_PCI_FUNCTION (ACPI_GET_ADDRESS (reg->address));
  649. pci_register   = (u16) (ACPI_PCI_REGISTER (ACPI_GET_ADDRESS (reg->address)) + offset);
  650. acpi_os_read_pci_configuration (&pci_id, pci_register, &value, width);
  651. break;
  652. }
  653. return value;
  654. }
  655. /******************************************************************************
  656.  *
  657.  * FUNCTION:    Acpi_hw_low_level_write
  658.  *
  659.  * PARAMETERS:  Width               - 8, 16, or 32
  660.  *              Value               - To be written
  661.  *              Register            - GAS register structure
  662.  *              Offset              - Offset from the base address in the GAS
  663.  *
  664.  *
  665.  * RETURN:      Value read
  666.  *
  667.  * DESCRIPTION: Read from either memory, IO, or PCI config space.
  668.  *
  669.  ******************************************************************************/
  670. void
  671. acpi_hw_low_level_write (
  672. u32                     width,
  673. u32                     value,
  674. acpi_generic_address    *reg,
  675. u32                     offset)
  676. {
  677. ACPI_PHYSICAL_ADDRESS   mem_address;
  678. ACPI_IO_ADDRESS         io_address;
  679. acpi_pci_id             pci_id;
  680. u16                     pci_register;
  681. FUNCTION_ENTRY ();
  682. /*
  683.  * Must have a valid pointer to a GAS structure, and
  684.  * a non-zero address within
  685.  */
  686. if ((!reg) ||
  687. (!ACPI_VALID_ADDRESS (reg->address))) {
  688. return;
  689. }
  690. /*
  691.  * Three address spaces supported:
  692.  * Memory, Io, or PCI config.
  693.  */
  694. switch (reg->address_space_id) {
  695. case ACPI_ADR_SPACE_SYSTEM_MEMORY:
  696. mem_address = (ACPI_PHYSICAL_ADDRESS) (ACPI_GET_ADDRESS (reg->address) + offset);
  697. acpi_os_write_memory (mem_address, value, width);
  698. break;
  699. case ACPI_ADR_SPACE_SYSTEM_IO:
  700. io_address = (ACPI_IO_ADDRESS) (ACPI_GET_ADDRESS (reg->address) + offset);
  701. acpi_os_write_port (io_address, value, width);
  702. break;
  703. case ACPI_ADR_SPACE_PCI_CONFIG:
  704. pci_id.segment = 0;
  705. pci_id.bus     = 0;
  706. pci_id.device  = ACPI_PCI_DEVICE (ACPI_GET_ADDRESS (reg->address));
  707. pci_id.function = ACPI_PCI_FUNCTION (ACPI_GET_ADDRESS (reg->address));
  708. pci_register   = (u16) (ACPI_PCI_REGISTER (ACPI_GET_ADDRESS (reg->address)) + offset);
  709. acpi_os_write_pci_configuration (&pci_id, pci_register, value, width);
  710. break;
  711. }
  712. }