patch-2.4.22 linux-2.4.22/drivers/acpi/hardware/hwregs.c
Next file: linux-2.4.22/drivers/acpi/hardware/hwsleep.c
Previous file: linux-2.4.22/drivers/acpi/hardware/hwgpe.c
Back to the patch index
Back to the overall index
- Lines: 1428
- Date:
2003-08-25 04:44:41.000000000 -0700
- Orig file:
linux-2.4.21/drivers/acpi/hardware/hwregs.c
- Orig date:
2001-10-24 14:06:22.000000000 -0700
diff -urN linux-2.4.21/drivers/acpi/hardware/hwregs.c linux-2.4.22/drivers/acpi/hardware/hwregs.c
@@ -3,71 +3,60 @@
*
* Module Name: hwregs - Read/write access functions for the various ACPI
* control and status registers.
- * $Revision: 110 $
*
******************************************************************************/
/*
- * Copyright (C) 2000, 2001 R. Byron Moore
+ * Copyright (C) 2000 - 2003, R. Byron Moore
+ * All rights reserved.
*
- * 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
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
*/
-#include "acpi.h"
-#include "achware.h"
-#include "acnamesp.h"
+#include <acpi/acpi.h>
+#include <acpi/acnamesp.h>
+#include <acpi/acevents.h>
#define _COMPONENT ACPI_HARDWARE
- MODULE_NAME ("hwregs")
+ ACPI_MODULE_NAME ("hwregs")
/*******************************************************************************
*
- * FUNCTION: Acpi_hw_get_bit_shift
+ * FUNCTION: acpi_hw_clear_acpi_status
*
- * PARAMETERS: Mask - Input mask to determine bit shift from.
- * Must have at least 1 bit set.
- *
- * RETURN: Bit location of the lsb of the mask
- *
- * DESCRIPTION: Returns the bit number for the low order bit that's set.
- *
- ******************************************************************************/
-
-u32
-acpi_hw_get_bit_shift (
- u32 mask)
-{
- u32 shift;
-
-
- FUNCTION_TRACE ("Hw_get_bit_shift");
-
-
- for (shift = 0; ((mask >> shift) & 1) == 0; shift++) { ; }
-
- return_VALUE (shift);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: Acpi_hw_clear_acpi_status
- *
- * PARAMETERS: none
+ * PARAMETERS: Flags - Lock the hardware or not
*
* RETURN: none
*
@@ -75,506 +64,403 @@
*
******************************************************************************/
-void
-acpi_hw_clear_acpi_status (void)
+acpi_status
+acpi_hw_clear_acpi_status (
+ u32 flags)
{
- u16 gpe_length;
- u16 index;
+ acpi_status status;
- FUNCTION_TRACE ("Hw_clear_acpi_status");
+ ACPI_FUNCTION_TRACE ("hw_clear_acpi_status");
ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %04X to %04X\n",
- ALL_FIXED_STS_BITS,
- (u16) ACPI_GET_ADDRESS (acpi_gbl_FADT->Xpm1a_evt_blk.address)));
+ ACPI_BITMASK_ALL_FIXED_STATUS,
+ (u16) acpi_gbl_FADT->xpm1a_evt_blk.address));
-
- acpi_ut_acquire_mutex (ACPI_MTX_HARDWARE);
-
- acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, PM1_STS, ALL_FIXED_STS_BITS);
-
-
- if (ACPI_VALID_ADDRESS (acpi_gbl_FADT->Xpm1b_evt_blk.address)) {
- acpi_os_write_port ((ACPI_IO_ADDRESS)
- ACPI_GET_ADDRESS (acpi_gbl_FADT->Xpm1b_evt_blk.address),
- ALL_FIXED_STS_BITS, 16);
+ if (flags & ACPI_MTX_LOCK) {
+ status = acpi_ut_acquire_mutex (ACPI_MTX_HARDWARE);
+ if (ACPI_FAILURE (status)) {
+ return_ACPI_STATUS (status);
+ }
}
- /* now clear the GPE Bits */
+ status = acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1_STATUS,
+ ACPI_BITMASK_ALL_FIXED_STATUS);
+ if (ACPI_FAILURE (status)) {
+ goto unlock_and_exit;
+ }
- if (acpi_gbl_FADT->gpe0blk_len) {
- gpe_length = (u16) DIV_2 (acpi_gbl_FADT->gpe0blk_len);
+ /* Clear the fixed events */
- for (index = 0; index < gpe_length; index++) {
- acpi_os_write_port ((ACPI_IO_ADDRESS) (
- ACPI_GET_ADDRESS (acpi_gbl_FADT->Xgpe0blk.address) + index),
- 0xFF, 8);
+ if (acpi_gbl_FADT->xpm1b_evt_blk.address) {
+ status = acpi_hw_low_level_write (16, ACPI_BITMASK_ALL_FIXED_STATUS,
+ &acpi_gbl_FADT->xpm1b_evt_blk);
+ if (ACPI_FAILURE (status)) {
+ goto unlock_and_exit;
}
}
- if (acpi_gbl_FADT->gpe1_blk_len) {
- gpe_length = (u16) DIV_2 (acpi_gbl_FADT->gpe1_blk_len);
+ /* Clear the GPE Bits in all GPE registers in all GPE blocks */
- for (index = 0; index < gpe_length; index++) {
- acpi_os_write_port ((ACPI_IO_ADDRESS) (
- ACPI_GET_ADDRESS (acpi_gbl_FADT->Xgpe1_blk.address) + index),
- 0xFF, 8);
- }
- }
+ status = acpi_ev_walk_gpe_list (acpi_hw_clear_gpe_block);
- acpi_ut_release_mutex (ACPI_MTX_HARDWARE);
- return_VOID;
+unlock_and_exit:
+ if (flags & ACPI_MTX_LOCK) {
+ (void) acpi_ut_release_mutex (ACPI_MTX_HARDWARE);
+ }
+ return_ACPI_STATUS (status);
}
/*******************************************************************************
*
- * FUNCTION: Acpi_hw_obtain_sleep_type_register_data
+ * FUNCTION: acpi_get_sleep_type_data
*
- * PARAMETERS: Sleep_state - Numeric state requested
- * *Slp_Typ_a - Pointer to byte to receive SLP_TYPa value
- * *Slp_Typ_b - Pointer to byte to receive SLP_TYPb value
+ * PARAMETERS: sleep_state - Numeric sleep state
+ * *sleep_type_a - Where SLP_TYPa is returned
+ * *sleep_type_b - Where SLP_TYPb is returned
*
* RETURN: Status - ACPI status
*
- * DESCRIPTION: Acpi_hw_obtain_sleep_type_register_data() obtains the SLP_TYP and
- * SLP_TYPb values for the sleep state requested.
+ * DESCRIPTION: Obtain the SLP_TYPa and SLP_TYPb values for the requested sleep
+ * state.
*
******************************************************************************/
acpi_status
-acpi_hw_obtain_sleep_type_register_data (
- u8 sleep_state,
- u8 *slp_typ_a,
- u8 *slp_typ_b)
+acpi_get_sleep_type_data (
+ u8 sleep_state,
+ u8 *sleep_type_a,
+ u8 *sleep_type_b)
{
- acpi_status status = AE_OK;
- acpi_operand_object *obj_desc;
+ acpi_status status = AE_OK;
+ union acpi_operand_object *obj_desc;
- FUNCTION_TRACE ("Hw_obtain_sleep_type_register_data");
+ ACPI_FUNCTION_TRACE ("acpi_get_sleep_type_data");
/*
- * Validate parameters
+ * Validate parameters
*/
if ((sleep_state > ACPI_S_STATES_MAX) ||
- !slp_typ_a || !slp_typ_b) {
+ !sleep_type_a || !sleep_type_b) {
return_ACPI_STATUS (AE_BAD_PARAMETER);
}
/*
- * Acpi_evaluate the namespace object containing the values for this state
+ * Evaluate the namespace object containing the values for this state
*/
- status = acpi_ns_evaluate_by_name ((NATIVE_CHAR *) acpi_gbl_db_sleep_states[sleep_state],
+ status = acpi_ns_evaluate_by_name ((char *) acpi_gbl_db_sleep_states[sleep_state],
NULL, &obj_desc);
if (ACPI_FAILURE (status)) {
+ ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%s while evaluating sleep_state [%s]\n",
+ acpi_format_exception (status), acpi_gbl_db_sleep_states[sleep_state]));
+
return_ACPI_STATUS (status);
}
+ /* Must have a return object */
+
if (!obj_desc) {
- REPORT_ERROR (("Missing Sleep State object\n"));
- return_ACPI_STATUS (AE_NOT_EXIST);
+ ACPI_REPORT_ERROR (("Missing Sleep State object\n"));
+ status = AE_NOT_EXIST;
}
- /*
- * We got something, now ensure it is correct. The object must
- * be a package and must have at least 2 numeric values as the
- * two elements
- */
+ /* It must be of type Package */
- /* Even though Acpi_evaluate_object resolves package references,
- * Ns_evaluate dpesn't. So, we do it here.
- */
- status = acpi_ut_resolve_package_references(obj_desc);
+ else if (ACPI_GET_OBJECT_TYPE (obj_desc) != ACPI_TYPE_PACKAGE) {
+ ACPI_REPORT_ERROR (("Sleep State object not a Package\n"));
+ status = AE_AML_OPERAND_TYPE;
+ }
- if (obj_desc->package.count < 2) {
- /* Must have at least two elements */
+ /* The package must have at least two elements */
- REPORT_ERROR (("Sleep State package does not have at least two elements\n"));
- status = AE_ERROR;
+ else if (obj_desc->package.count < 2) {
+ ACPI_REPORT_ERROR (("Sleep State package does not have at least two elements\n"));
+ status = AE_AML_NO_OPERAND;
}
- else if (((obj_desc->package.elements[0])->common.type !=
- ACPI_TYPE_INTEGER) ||
- ((obj_desc->package.elements[1])->common.type !=
- ACPI_TYPE_INTEGER)) {
- /* Must have two */
+ /* The first two elements must both be of type Integer */
- REPORT_ERROR (("Sleep State package elements are not both of type Number\n"));
- status = AE_ERROR;
+ else if ((ACPI_GET_OBJECT_TYPE (obj_desc->package.elements[0]) != ACPI_TYPE_INTEGER) ||
+ (ACPI_GET_OBJECT_TYPE (obj_desc->package.elements[1]) != ACPI_TYPE_INTEGER)) {
+ ACPI_REPORT_ERROR (("Sleep State package elements are not both Integers (%s, %s)\n",
+ acpi_ut_get_object_type_name (obj_desc->package.elements[0]),
+ acpi_ut_get_object_type_name (obj_desc->package.elements[1])));
+ status = AE_AML_OPERAND_TYPE;
}
-
else {
/*
- * Valid _Sx_ package size, type, and value
+ * Valid _Sx_ package size, type, and value
*/
- *slp_typ_a = (u8) (obj_desc->package.elements[0])->integer.value;
-
- *slp_typ_b = (u8) (obj_desc->package.elements[1])->integer.value;
+ *sleep_type_a = (u8) (obj_desc->package.elements[0])->integer.value;
+ *sleep_type_b = (u8) (obj_desc->package.elements[1])->integer.value;
}
-
if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Bad Sleep object %p type %X\n",
- obj_desc, obj_desc->common.type));
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "While evaluating sleep_state [%s], bad Sleep object %p type %s\n",
+ acpi_gbl_db_sleep_states[sleep_state], obj_desc, acpi_ut_get_object_type_name (obj_desc)));
}
acpi_ut_remove_reference (obj_desc);
-
return_ACPI_STATUS (status);
}
/*******************************************************************************
*
- * FUNCTION: Acpi_hw_register_bit_access
+ * FUNCTION: acpi_hw_get_register_bit_mask
*
- * PARAMETERS: Read_write - Either ACPI_READ or ACPI_WRITE.
- * Use_lock - Lock the hardware
- * Register_id - index of ACPI Register to access
- * Value - (only used on write) value to write to the
- * Register. Shifted all the way right.
+ * PARAMETERS: register_id - Index of ACPI Register to access
*
- * RETURN: Value written to or read from specified Register. This value
- * is shifted all the way right.
+ * RETURN: The bit mask to be used when accessing the register
*
- * DESCRIPTION: Generic ACPI Register read/write function.
+ * DESCRIPTION: Map register_id into a register bit mask.
*
******************************************************************************/
-u32
-acpi_hw_register_bit_access (
- NATIVE_UINT read_write,
- u8 use_lock,
- u32 register_id,
- ...) /* Value (only used on write) */
+struct acpi_bit_register_info *
+acpi_hw_get_bit_register_info (
+ u32 register_id)
{
- u32 register_value = 0;
- u32 mask = 0;
- u32 value = 0;
- va_list marker;
-
-
- FUNCTION_TRACE ("Hw_register_bit_access");
+ ACPI_FUNCTION_NAME ("hw_get_bit_register_info");
- if (read_write == ACPI_WRITE) {
- va_start (marker, register_id);
- value = va_arg (marker, u32);
- va_end (marker);
+ if (register_id > ACPI_BITREG_MAX) {
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid bit_register ID: %X\n", register_id));
+ return (NULL);
}
- if (ACPI_MTX_LOCK == use_lock) {
- acpi_ut_acquire_mutex (ACPI_MTX_HARDWARE);
- }
+ return (&acpi_gbl_bit_register_info[register_id]);
+}
- /*
- * Decode the Register ID
- * Register id = Register block id | bit id
- *
- * Check bit id to fine locate Register offset.
- * Check Mask to determine Register offset, and then read-write.
- */
- switch (REGISTER_BLOCK_ID (register_id)) {
- case PM1_STS:
- switch (register_id) {
- case TMR_STS:
- mask = TMR_STS_MASK;
- break;
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_get_register
+ *
+ * PARAMETERS: register_id - ID of ACPI bit_register to access
+ * return_value - Value that was read from the register
+ * Flags - Lock the hardware or not
+ *
+ * RETURN: Value is read from specified Register. Value returned is
+ * normalized to bit0 (is shifted all the way right)
+ *
+ * DESCRIPTION: ACPI bit_register read function.
+ *
+ ******************************************************************************/
- case BM_STS:
- mask = BM_STS_MASK;
- break;
+acpi_status
+acpi_get_register (
+ u32 register_id,
+ u32 *return_value,
+ u32 flags)
+{
+ u32 register_value = 0;
+ struct acpi_bit_register_info *bit_reg_info;
+ acpi_status status;
- case GBL_STS:
- mask = GBL_STS_MASK;
- break;
- case PWRBTN_STS:
- mask = PWRBTN_STS_MASK;
- break;
+ ACPI_FUNCTION_TRACE ("acpi_get_register");
- case SLPBTN_STS:
- mask = SLPBTN_STS_MASK;
- break;
- case RTC_STS:
- mask = RTC_STS_MASK;
- break;
+ /* Get the info structure corresponding to the requested ACPI Register */
- case WAK_STS:
- mask = WAK_STS_MASK;
- break;
+ bit_reg_info = acpi_hw_get_bit_register_info (register_id);
+ if (!bit_reg_info) {
+ return_ACPI_STATUS (AE_BAD_PARAMETER);
+ }
- default:
- mask = 0;
- break;
+ if (flags & ACPI_MTX_LOCK) {
+ status = acpi_ut_acquire_mutex (ACPI_MTX_HARDWARE);
+ if (ACPI_FAILURE (status)) {
+ return_ACPI_STATUS (status);
}
+ }
+
+ status = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK,
+ bit_reg_info->parent_register, ®ister_value);
- register_value = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, PM1_STS);
+ if (flags & ACPI_MTX_LOCK) {
+ (void) acpi_ut_release_mutex (ACPI_MTX_HARDWARE);
+ }
- if (read_write == ACPI_WRITE) {
- /*
- * Status Registers are different from the rest. Clear by
- * writing 1, writing 0 has no effect. So, the only relevent
- * information is the single bit we're interested in, all
- * others should be written as 0 so they will be left
- * unchanged
- */
- value <<= acpi_hw_get_bit_shift (mask);
- value &= mask;
+ if (ACPI_SUCCESS (status)) {
+ /* Normalize the value that was read */
- if (value) {
- acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, PM1_STS,
- (u16) value);
- register_value = 0;
- }
- }
+ register_value = ((register_value & bit_reg_info->access_bit_mask)
+ >> bit_reg_info->bit_position);
- break;
+ *return_value = register_value;
+ ACPI_DEBUG_PRINT ((ACPI_DB_IO, "Read value %8.8X register %X\n",
+ register_value, bit_reg_info->parent_register));
+ }
- case PM1_EN:
+ return_ACPI_STATUS (status);
+}
- switch (register_id) {
- case TMR_EN:
- mask = TMR_EN_MASK;
- break;
- case GBL_EN:
- mask = GBL_EN_MASK;
- break;
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_set_register
+ *
+ * PARAMETERS: register_id - ID of ACPI bit_register to access
+ * Value - (only used on write) value to write to the
+ * Register, NOT pre-normalized to the bit pos.
+ * Flags - Lock the hardware or not
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: ACPI Bit Register write function.
+ *
+ ******************************************************************************/
- case PWRBTN_EN:
- mask = PWRBTN_EN_MASK;
- break;
+acpi_status
+acpi_set_register (
+ u32 register_id,
+ u32 value,
+ u32 flags)
+{
+ u32 register_value = 0;
+ struct acpi_bit_register_info *bit_reg_info;
+ acpi_status status;
- case SLPBTN_EN:
- mask = SLPBTN_EN_MASK;
- break;
- case RTC_EN:
- mask = RTC_EN_MASK;
- break;
+ ACPI_FUNCTION_TRACE_U32 ("acpi_set_register", register_id);
- default:
- mask = 0;
- break;
- }
- register_value = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, PM1_EN);
+ /* Get the info structure corresponding to the requested ACPI Register */
- if (read_write == ACPI_WRITE) {
- register_value &= ~mask;
- value <<= acpi_hw_get_bit_shift (mask);
- value &= mask;
- register_value |= value;
+ bit_reg_info = acpi_hw_get_bit_register_info (register_id);
+ if (!bit_reg_info) {
+ ACPI_REPORT_ERROR (("Bad ACPI HW register_id: %X\n", register_id));
+ return_ACPI_STATUS (AE_BAD_PARAMETER);
+ }
- acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, PM1_EN, (u16) register_value);
+ if (flags & ACPI_MTX_LOCK) {
+ status = acpi_ut_acquire_mutex (ACPI_MTX_HARDWARE);
+ if (ACPI_FAILURE (status)) {
+ return_ACPI_STATUS (status);
}
+ }
- break;
+ /* Always do a register read first so we can insert the new bits */
+ status = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK,
+ bit_reg_info->parent_register, ®ister_value);
+ if (ACPI_FAILURE (status)) {
+ goto unlock_and_exit;
+ }
- case PM1_CONTROL:
+ /*
+ * Decode the Register ID
+ * Register ID = [Register block ID] | [bit ID]
+ *
+ * Check bit ID to fine locate Register offset.
+ * Check Mask to determine Register offset, and then read-write.
+ */
+ switch (bit_reg_info->parent_register) {
+ case ACPI_REGISTER_PM1_STATUS:
- switch (register_id) {
- case SCI_EN:
- mask = SCI_EN_MASK;
- break;
+ /*
+ * Status Registers are different from the rest. Clear by
+ * writing 1, and writing 0 has no effect. So, the only relevant
+ * information is the single bit we're interested in, all others should
+ * be written as 0 so they will be left unchanged.
+ */
+ value = ACPI_REGISTER_PREPARE_BITS (value,
+ bit_reg_info->bit_position, bit_reg_info->access_bit_mask);
+ if (value) {
+ status = acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK,
+ ACPI_REGISTER_PM1_STATUS, (u16) value);
+ register_value = 0;
+ }
+ break;
- case BM_RLD:
- mask = BM_RLD_MASK;
- break;
- case GBL_RLS:
- mask = GBL_RLS_MASK;
- break;
+ case ACPI_REGISTER_PM1_ENABLE:
- case SLP_TYPE_A:
- case SLP_TYPE_B:
- mask = SLP_TYPE_X_MASK;
- break;
+ ACPI_REGISTER_INSERT_VALUE (register_value, bit_reg_info->bit_position,
+ bit_reg_info->access_bit_mask, value);
- case SLP_EN:
- mask = SLP_EN_MASK;
- break;
+ status = acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK,
+ ACPI_REGISTER_PM1_ENABLE, (u16) register_value);
+ break;
- default:
- mask = 0;
- break;
- }
+ case ACPI_REGISTER_PM1_CONTROL:
/*
- * Read the PM1 Control register.
+ * Write the PM1 Control register.
* Note that at this level, the fact that there are actually TWO
- * registers (A and B) and that B may not exist, are abstracted.
+ * registers (A and B - and B may not exist) is abstracted.
*/
- register_value = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, PM1_CONTROL);
-
ACPI_DEBUG_PRINT ((ACPI_DB_IO, "PM1 control: Read %X\n", register_value));
- if (read_write == ACPI_WRITE) {
- register_value &= ~mask;
- value <<= acpi_hw_get_bit_shift (mask);
- value &= mask;
- register_value |= value;
+ ACPI_REGISTER_INSERT_VALUE (register_value, bit_reg_info->bit_position,
+ bit_reg_info->access_bit_mask, value);
- /*
- * SLP_TYPE_x Registers are written differently
- * than any other control Registers with
- * respect to A and B Registers. The value
- * for A may be different than the value for B
- *
- * Therefore, pass the Register_id, not just generic PM1_CONTROL,
- * because we need to do different things. Yuck.
- */
- acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, register_id,
- (u16) register_value);
- }
+ status = acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK,
+ ACPI_REGISTER_PM1_CONTROL, (u16) register_value);
break;
- case PM2_CONTROL:
+ case ACPI_REGISTER_PM2_CONTROL:
- switch (register_id) {
- case ARB_DIS:
- mask = ARB_DIS_MASK;
- break;
-
- default:
- mask = 0;
- break;
+ status = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK,
+ ACPI_REGISTER_PM2_CONTROL, ®ister_value);
+ if (ACPI_FAILURE (status)) {
+ goto unlock_and_exit;
}
- register_value = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, PM2_CONTROL);
-
ACPI_DEBUG_PRINT ((ACPI_DB_IO, "PM2 control: Read %X from %8.8X%8.8X\n",
- register_value, HIDWORD(acpi_gbl_FADT->Xpm2_cnt_blk.address),
- LODWORD(acpi_gbl_FADT->Xpm2_cnt_blk.address)));
-
- if (read_write == ACPI_WRITE) {
- register_value &= ~mask;
- value <<= acpi_hw_get_bit_shift (mask);
- value &= mask;
- register_value |= value;
-
- ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %04X to %8.8X%8.8X\n",
- register_value,
- HIDWORD(acpi_gbl_FADT->Xpm2_cnt_blk.address),
- LODWORD(acpi_gbl_FADT->Xpm2_cnt_blk.address)));
-
- acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK,
- PM2_CONTROL, (u8) (register_value));
- }
- break;
-
-
- case PM_TIMER:
-
- mask = TMR_VAL_MASK;
- register_value = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK,
- PM_TIMER);
- ACPI_DEBUG_PRINT ((ACPI_DB_IO, "PM_TIMER: Read %X from %8.8X%8.8X\n",
register_value,
- HIDWORD(acpi_gbl_FADT->Xpm_tmr_blk.address),
- LODWORD(acpi_gbl_FADT->Xpm_tmr_blk.address)));
-
- break;
-
-
- case GPE1_EN_BLOCK:
- case GPE1_STS_BLOCK:
- case GPE0_EN_BLOCK:
- case GPE0_STS_BLOCK:
-
- /* Determine the bit to be accessed
- *
- * (u32) Register_id:
- * 31 24 16 8 0
- * +--------+--------+--------+--------+
- * | gpe_block_id | gpe_bit_number |
- * +--------+--------+--------+--------+
- *
- * gpe_block_id is one of GPE[01]_EN_BLOCK and GPE[01]_STS_BLOCK
- * gpe_bit_number is relative from the gpe_block (0x00~0xFF)
- */
- mask = REGISTER_BIT_ID(register_id); /* gpe_bit_number */
- register_id = REGISTER_BLOCK_ID(register_id) | (mask >> 3);
- mask = acpi_gbl_decode_to8bit [mask % 8];
-
- /*
- * The base address of the GPE 0 Register Block
- * Plus 1/2 the length of the GPE 0 Register Block
- * The enable Register is the Register following the Status Register
- * and each Register is defined as 1/2 of the total Register Block
- */
-
- /*
- * This sets the bit within Enable_bit that needs to be written to
- * the Register indicated in Mask to a 1, all others are 0
- */
+ ACPI_HIDWORD (acpi_gbl_FADT->xpm2_cnt_blk.address),
+ ACPI_LODWORD (acpi_gbl_FADT->xpm2_cnt_blk.address)));
- /* Now get the current Enable Bits in the selected Reg */
+ ACPI_REGISTER_INSERT_VALUE (register_value, bit_reg_info->bit_position,
+ bit_reg_info->access_bit_mask, value);
- register_value = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, register_id);
- ACPI_DEBUG_PRINT ((ACPI_DB_IO, "GPE Enable bits: Read %X from %X\n",
- register_value, register_id));
-
- if (read_write == ACPI_WRITE) {
- register_value &= ~mask;
- value <<= acpi_hw_get_bit_shift (mask);
- value &= mask;
- register_value |= value;
+ ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %4.4X to %8.8X%8.8X\n",
+ register_value,
+ ACPI_HIDWORD (acpi_gbl_FADT->xpm2_cnt_blk.address),
+ ACPI_LODWORD (acpi_gbl_FADT->xpm2_cnt_blk.address)));
- /*
- * This write will put the Action state into the General Purpose
- * Enable Register indexed by the value in Mask
- */
- ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %04X to %04X\n",
- register_value, register_id));
- acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, register_id,
- (u8) register_value);
- register_value = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK,
- register_id);
- }
+ status = acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK,
+ ACPI_REGISTER_PM2_CONTROL, (u8) (register_value));
break;
- case SMI_CMD_BLOCK:
- case PROCESSOR_BLOCK:
-
- /* Not used by any callers at this time - therefore, not implemented */
-
default:
-
- mask = 0;
break;
}
- if (ACPI_MTX_LOCK == use_lock) {
- acpi_ut_release_mutex (ACPI_MTX_HARDWARE);
+
+unlock_and_exit:
+
+ if (flags & ACPI_MTX_LOCK) {
+ (void) acpi_ut_release_mutex (ACPI_MTX_HARDWARE);
}
+ /* Normalize the value that was read */
- register_value &= mask;
- register_value >>= acpi_hw_get_bit_shift (mask);
+ ACPI_DEBUG_EXEC (register_value = ((register_value & bit_reg_info->access_bit_mask) >> bit_reg_info->bit_position));
- ACPI_DEBUG_PRINT ((ACPI_DB_IO, "Register I/O: returning %X\n", register_value));
- return_VALUE (register_value);
+ ACPI_DEBUG_PRINT ((ACPI_DB_IO, "Set bits: %8.8X actual %8.8X register %X\n",
+ value, register_value, bit_reg_info->parent_register));
+ return_ACPI_STATUS (status);
}
/******************************************************************************
*
- * FUNCTION: Acpi_hw_register_read
+ * FUNCTION: acpi_hw_register_read
*
- * PARAMETERS: Use_lock - Mutex hw access.
- * Register_id - Register_iD + Offset.
+ * PARAMETERS: use_lock - Mutex hw access.
+ * register_id - register_iD + Offset.
*
* RETURN: Value read or written.
*
@@ -583,112 +469,109 @@
*
******************************************************************************/
-u32
+acpi_status
acpi_hw_register_read (
- u8 use_lock,
- u32 register_id)
+ u8 use_lock,
+ u32 register_id,
+ u32 *return_value)
{
- u32 value = 0;
- u32 bank_offset;
+ u32 value1 = 0;
+ u32 value2 = 0;
+ acpi_status status;
- FUNCTION_TRACE ("Hw_register_read");
+ ACPI_FUNCTION_TRACE ("hw_register_read");
if (ACPI_MTX_LOCK == use_lock) {
- acpi_ut_acquire_mutex (ACPI_MTX_HARDWARE);
+ status = acpi_ut_acquire_mutex (ACPI_MTX_HARDWARE);
+ if (ACPI_FAILURE (status)) {
+ return_ACPI_STATUS (status);
+ }
}
+ switch (register_id) {
+ case ACPI_REGISTER_PM1_STATUS: /* 16-bit access */
- switch (REGISTER_BLOCK_ID(register_id)) {
- case PM1_STS: /* 16-bit access */
-
- value = acpi_hw_low_level_read (16, &acpi_gbl_FADT->Xpm1a_evt_blk, 0);
- value |= acpi_hw_low_level_read (16, &acpi_gbl_FADT->Xpm1b_evt_blk, 0);
- break;
-
+ status = acpi_hw_low_level_read (16, &value1, &acpi_gbl_FADT->xpm1a_evt_blk);
+ if (ACPI_FAILURE (status)) {
+ goto unlock_and_exit;
+ }
- case PM1_EN: /* 16-bit access*/
+ /* PM1B is optional */
- bank_offset = DIV_2 (acpi_gbl_FADT->pm1_evt_len);
- value = acpi_hw_low_level_read (16, &acpi_gbl_FADT->Xpm1a_evt_blk, bank_offset);
- value |= acpi_hw_low_level_read (16, &acpi_gbl_FADT->Xpm1b_evt_blk, bank_offset);
+ status = acpi_hw_low_level_read (16, &value2, &acpi_gbl_FADT->xpm1b_evt_blk);
+ value1 |= value2;
break;
- case PM1_CONTROL: /* 16-bit access */
-
- value = acpi_hw_low_level_read (16, &acpi_gbl_FADT->Xpm1a_cnt_blk, 0);
- value |= acpi_hw_low_level_read (16, &acpi_gbl_FADT->Xpm1b_cnt_blk, 0);
- break;
+ case ACPI_REGISTER_PM1_ENABLE: /* 16-bit access */
+ status = acpi_hw_low_level_read (16, &value1, &acpi_gbl_xpm1a_enable);
+ if (ACPI_FAILURE (status)) {
+ goto unlock_and_exit;
+ }
- case PM2_CONTROL: /* 8-bit access */
+ /* PM1B is optional */
- value = acpi_hw_low_level_read (8, &acpi_gbl_FADT->Xpm2_cnt_blk, 0);
+ status = acpi_hw_low_level_read (16, &value2, &acpi_gbl_xpm1b_enable);
+ value1 |= value2;
break;
- case PM_TIMER: /* 32-bit access */
-
- value = acpi_hw_low_level_read (32, &acpi_gbl_FADT->Xpm_tmr_blk, 0);
- break;
-
+ case ACPI_REGISTER_PM1_CONTROL: /* 16-bit access */
- /*
- * For the GPE? Blocks, the lower word of Register_id contains the
- * byte offset for which to read, as each part of each block may be
- * several bytes long.
- */
- case GPE0_STS_BLOCK: /* 8-bit access */
+ status = acpi_hw_low_level_read (16, &value1, &acpi_gbl_FADT->xpm1a_cnt_blk);
+ if (ACPI_FAILURE (status)) {
+ goto unlock_and_exit;
+ }
- bank_offset = REGISTER_BIT_ID(register_id);
- value = acpi_hw_low_level_read (8, &acpi_gbl_FADT->Xgpe0blk, bank_offset);
+ status = acpi_hw_low_level_read (16, &value2, &acpi_gbl_FADT->xpm1b_cnt_blk);
+ value1 |= value2;
break;
- case GPE0_EN_BLOCK: /* 8-bit access */
-
- bank_offset = DIV_2 (acpi_gbl_FADT->gpe0blk_len) + REGISTER_BIT_ID(register_id);
- value = acpi_hw_low_level_read (8, &acpi_gbl_FADT->Xgpe0blk, bank_offset);
- break;
- case GPE1_STS_BLOCK: /* 8-bit access */
+ case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */
- bank_offset = REGISTER_BIT_ID(register_id);
- value = acpi_hw_low_level_read (8, &acpi_gbl_FADT->Xgpe1_blk, bank_offset);
+ status = acpi_hw_low_level_read (8, &value1, &acpi_gbl_FADT->xpm2_cnt_blk);
break;
- case GPE1_EN_BLOCK: /* 8-bit access */
- bank_offset = DIV_2 (acpi_gbl_FADT->gpe1_blk_len) + REGISTER_BIT_ID(register_id);
- value = acpi_hw_low_level_read (8, &acpi_gbl_FADT->Xgpe1_blk, bank_offset);
+ case ACPI_REGISTER_PM_TIMER: /* 32-bit access */
+
+ status = acpi_hw_low_level_read (32, &value1, &acpi_gbl_FADT->xpm_tmr_blk);
break;
- case SMI_CMD_BLOCK: /* 8bit */
+ case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */
- acpi_os_read_port (acpi_gbl_FADT->smi_cmd, &value, 8);
+ status = acpi_os_read_port (acpi_gbl_FADT->smi_cmd, &value1, 8);
break;
default:
- /* Value will be returned as 0 */
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown Register ID: %X\n", register_id));
+ status = AE_BAD_PARAMETER;
break;
}
-
+unlock_and_exit:
if (ACPI_MTX_LOCK == use_lock) {
- acpi_ut_release_mutex (ACPI_MTX_HARDWARE);
+ (void) acpi_ut_release_mutex (ACPI_MTX_HARDWARE);
+ }
+
+ if (ACPI_SUCCESS (status)) {
+ *return_value = value1;
}
- return_VALUE (value);
+ return_ACPI_STATUS (status);
}
/******************************************************************************
*
- * FUNCTION: Acpi_hw_register_write
+ * FUNCTION: acpi_hw_register_write
*
- * PARAMETERS: Use_lock - Mutex hw access.
- * Register_id - Register_iD + Offset.
+ * PARAMETERS: use_lock - Mutex hw access.
+ * register_id - register_iD + Offset.
*
* RETURN: Value read or written.
*
@@ -697,179 +580,165 @@
*
******************************************************************************/
-void
+acpi_status
acpi_hw_register_write (
- u8 use_lock,
- u32 register_id,
- u32 value)
+ u8 use_lock,
+ u32 register_id,
+ u32 value)
{
- u32 bank_offset;
+ acpi_status status;
- FUNCTION_TRACE ("Hw_register_write");
+ ACPI_FUNCTION_TRACE ("hw_register_write");
if (ACPI_MTX_LOCK == use_lock) {
- acpi_ut_acquire_mutex (ACPI_MTX_HARDWARE);
+ status = acpi_ut_acquire_mutex (ACPI_MTX_HARDWARE);
+ if (ACPI_FAILURE (status)) {
+ return_ACPI_STATUS (status);
+ }
}
+ switch (register_id) {
+ case ACPI_REGISTER_PM1_STATUS: /* 16-bit access */
- switch (REGISTER_BLOCK_ID (register_id)) {
- case PM1_STS: /* 16-bit access */
-
- acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1a_evt_blk, 0);
- acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1b_evt_blk, 0);
- break;
-
-
- case PM1_EN: /* 16-bit access*/
-
- bank_offset = DIV_2 (acpi_gbl_FADT->pm1_evt_len);
- acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1a_evt_blk, bank_offset);
- acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1b_evt_blk, bank_offset);
- break;
-
+ status = acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->xpm1a_evt_blk);
+ if (ACPI_FAILURE (status)) {
+ goto unlock_and_exit;
+ }
- case PM1_CONTROL: /* 16-bit access */
+ /* PM1B is optional */
- acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1a_cnt_blk, 0);
- acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1b_cnt_blk, 0);
+ status = acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->xpm1b_evt_blk);
break;
- case PM1A_CONTROL: /* 16-bit access */
-
- acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1a_cnt_blk, 0);
- break;
+ case ACPI_REGISTER_PM1_ENABLE: /* 16-bit access*/
+ status = acpi_hw_low_level_write (16, value, &acpi_gbl_xpm1a_enable);
+ if (ACPI_FAILURE (status)) {
+ goto unlock_and_exit;
+ }
- case PM1B_CONTROL: /* 16-bit access */
+ /* PM1B is optional */
- acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1b_cnt_blk, 0);
+ status = acpi_hw_low_level_write (16, value, &acpi_gbl_xpm1b_enable);
break;
- case PM2_CONTROL: /* 8-bit access */
-
- acpi_hw_low_level_write (8, value, &acpi_gbl_FADT->Xpm2_cnt_blk, 0);
- break;
-
+ case ACPI_REGISTER_PM1_CONTROL: /* 16-bit access */
- case PM_TIMER: /* 32-bit access */
+ status = acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->xpm1a_cnt_blk);
+ if (ACPI_FAILURE (status)) {
+ goto unlock_and_exit;
+ }
- acpi_hw_low_level_write (32, value, &acpi_gbl_FADT->Xpm_tmr_blk, 0);
+ status = acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->xpm1b_cnt_blk);
break;
- case GPE0_STS_BLOCK: /* 8-bit access */
+ case ACPI_REGISTER_PM1A_CONTROL: /* 16-bit access */
- bank_offset = REGISTER_BIT_ID(register_id);
- acpi_hw_low_level_write (8, value, &acpi_gbl_FADT->Xgpe0blk, bank_offset);
+ status = acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->xpm1a_cnt_blk);
break;
- case GPE0_EN_BLOCK: /* 8-bit access */
+ case ACPI_REGISTER_PM1B_CONTROL: /* 16-bit access */
- bank_offset = DIV_2 (acpi_gbl_FADT->gpe0blk_len) + REGISTER_BIT_ID(register_id);
- acpi_hw_low_level_write (8, value, &acpi_gbl_FADT->Xgpe0blk, bank_offset);
+ status = acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->xpm1b_cnt_blk);
break;
- case GPE1_STS_BLOCK: /* 8-bit access */
+ case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */
- bank_offset = REGISTER_BIT_ID(register_id);
- acpi_hw_low_level_write (8, value, &acpi_gbl_FADT->Xgpe1_blk, bank_offset);
+ status = acpi_hw_low_level_write (8, value, &acpi_gbl_FADT->xpm2_cnt_blk);
break;
- case GPE1_EN_BLOCK: /* 8-bit access */
+ case ACPI_REGISTER_PM_TIMER: /* 32-bit access */
- bank_offset = DIV_2 (acpi_gbl_FADT->gpe1_blk_len) + REGISTER_BIT_ID(register_id);
- acpi_hw_low_level_write (8, value, &acpi_gbl_FADT->Xgpe1_blk, bank_offset);
+ status = acpi_hw_low_level_write (32, value, &acpi_gbl_FADT->xpm_tmr_blk);
break;
- case SMI_CMD_BLOCK: /* 8bit */
+ case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */
- /* For 2.0, SMI_CMD is always in IO space */
- /* TBD: what about 1.0? 0.71? */
+ /* SMI_CMD is currently always in IO space */
- acpi_os_write_port (acpi_gbl_FADT->smi_cmd, value, 8);
+ status = acpi_os_write_port (acpi_gbl_FADT->smi_cmd, value, 8);
break;
default:
- value = 0;
+ status = AE_BAD_PARAMETER;
break;
}
-
+unlock_and_exit:
if (ACPI_MTX_LOCK == use_lock) {
- acpi_ut_release_mutex (ACPI_MTX_HARDWARE);
+ (void) acpi_ut_release_mutex (ACPI_MTX_HARDWARE);
}
- return_VOID;
+ return_ACPI_STATUS (status);
}
/******************************************************************************
*
- * FUNCTION: Acpi_hw_low_level_read
+ * FUNCTION: acpi_hw_low_level_read
*
- * PARAMETERS: Register - GAS register structure
- * Offset - Offset from the base address in the GAS
- * Width - 8, 16, or 32
+ * PARAMETERS: Width - 8, 16, or 32
+ * Value - Where the value is returned
+ * Register - GAS register structure
*
- * RETURN: Value read
+ * RETURN: Status
*
* DESCRIPTION: Read from either memory, IO, or PCI config space.
*
******************************************************************************/
-u32
+acpi_status
acpi_hw_low_level_read (
- u32 width,
- acpi_generic_address *reg,
- u32 offset)
+ u32 width,
+ u32 *value,
+ struct acpi_generic_address *reg)
{
- u32 value = 0;
- ACPI_PHYSICAL_ADDRESS mem_address;
- ACPI_IO_ADDRESS io_address;
- acpi_pci_id pci_id;
- u16 pci_register;
+ struct acpi_pci_id pci_id;
+ u16 pci_register;
+ acpi_status status;
- FUNCTION_ENTRY ();
+ ACPI_FUNCTION_NAME ("hw_low_level_read");
/*
* Must have a valid pointer to a GAS structure, and
- * a non-zero address within
+ * a non-zero address within. However, don't return an error
+ * because the PM1A/B code must not fail if B isn't present.
*/
if ((!reg) ||
- (!ACPI_VALID_ADDRESS (reg->address))) {
- return 0;
+ (!reg->address)) {
+ return (AE_OK);
}
-
+ *value = 0;
/*
* Three address spaces supported:
- * Memory, Io, or PCI config.
+ * Memory, IO, or PCI_Config.
*/
switch (reg->address_space_id) {
case ACPI_ADR_SPACE_SYSTEM_MEMORY:
- mem_address = (ACPI_PHYSICAL_ADDRESS) (ACPI_GET_ADDRESS (reg->address) + offset);
-
- acpi_os_read_memory (mem_address, &value, width);
+ status = acpi_os_read_memory (
+ (acpi_physical_address) reg->address,
+ value, width);
break;
case ACPI_ADR_SPACE_SYSTEM_IO:
- io_address = (ACPI_IO_ADDRESS) (ACPI_GET_ADDRESS (reg->address) + offset);
-
- acpi_os_read_port (io_address, &value, width);
+ status = acpi_os_read_port ((acpi_io_address) reg->address,
+ value, width);
break;
@@ -877,78 +746,86 @@
pci_id.segment = 0;
pci_id.bus = 0;
- pci_id.device = ACPI_PCI_DEVICE (ACPI_GET_ADDRESS (reg->address));
- pci_id.function = ACPI_PCI_FUNCTION (ACPI_GET_ADDRESS (reg->address));
- pci_register = (u16) (ACPI_PCI_REGISTER (ACPI_GET_ADDRESS (reg->address)) + offset);
+ pci_id.device = ACPI_PCI_DEVICE (reg->address);
+ pci_id.function = ACPI_PCI_FUNCTION (reg->address);
+ pci_register = (u16) ACPI_PCI_REGISTER (reg->address);
- acpi_os_read_pci_configuration (&pci_id, pci_register, &value, width);
+ status = acpi_os_read_pci_configuration (&pci_id, pci_register,
+ value, width);
break;
+
+
+ default:
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
+ "Unsupported address space: %X\n", reg->address_space_id));
+ return (AE_BAD_PARAMETER);
}
- return value;
+ ACPI_DEBUG_PRINT ((ACPI_DB_IO, "Read: %8.8X width %2d from %8.8X%8.8X (%s)\n",
+ *value, width,
+ ACPI_HIDWORD (reg->address),
+ ACPI_LODWORD (reg->address),
+ acpi_ut_get_region_name (reg->address_space_id)));
+
+ return (status);
}
/******************************************************************************
*
- * FUNCTION: Acpi_hw_low_level_write
+ * FUNCTION: acpi_hw_low_level_write
*
* PARAMETERS: Width - 8, 16, or 32
* Value - To be written
* Register - GAS register structure
- * Offset - Offset from the base address in the GAS
- *
*
- * RETURN: Value read
+ * RETURN: Status
*
- * DESCRIPTION: Read from either memory, IO, or PCI config space.
+ * DESCRIPTION: Write to either memory, IO, or PCI config space.
*
******************************************************************************/
-void
+acpi_status
acpi_hw_low_level_write (
- u32 width,
- u32 value,
- acpi_generic_address *reg,
- u32 offset)
+ u32 width,
+ u32 value,
+ struct acpi_generic_address *reg)
{
- ACPI_PHYSICAL_ADDRESS mem_address;
- ACPI_IO_ADDRESS io_address;
- acpi_pci_id pci_id;
- u16 pci_register;
+ struct acpi_pci_id pci_id;
+ u16 pci_register;
+ acpi_status status;
- FUNCTION_ENTRY ();
+ ACPI_FUNCTION_NAME ("hw_low_level_write");
/*
* Must have a valid pointer to a GAS structure, and
- * a non-zero address within
+ * a non-zero address within. However, don't return an error
+ * because the PM1A/B code must not fail if B isn't present.
*/
if ((!reg) ||
- (!ACPI_VALID_ADDRESS (reg->address))) {
- return;
+ (!reg->address)) {
+ return (AE_OK);
}
-
/*
* Three address spaces supported:
- * Memory, Io, or PCI config.
+ * Memory, IO, or PCI_Config.
*/
switch (reg->address_space_id) {
case ACPI_ADR_SPACE_SYSTEM_MEMORY:
- mem_address = (ACPI_PHYSICAL_ADDRESS) (ACPI_GET_ADDRESS (reg->address) + offset);
-
- acpi_os_write_memory (mem_address, value, width);
+ status = acpi_os_write_memory (
+ (acpi_physical_address) reg->address,
+ value, width);
break;
case ACPI_ADR_SPACE_SYSTEM_IO:
- io_address = (ACPI_IO_ADDRESS) (ACPI_GET_ADDRESS (reg->address) + offset);
-
- acpi_os_write_port (io_address, value, width);
+ status = acpi_os_write_port ((acpi_io_address) reg->address,
+ value, width);
break;
@@ -956,11 +833,26 @@
pci_id.segment = 0;
pci_id.bus = 0;
- pci_id.device = ACPI_PCI_DEVICE (ACPI_GET_ADDRESS (reg->address));
- pci_id.function = ACPI_PCI_FUNCTION (ACPI_GET_ADDRESS (reg->address));
- pci_register = (u16) (ACPI_PCI_REGISTER (ACPI_GET_ADDRESS (reg->address)) + offset);
+ pci_id.device = ACPI_PCI_DEVICE (reg->address);
+ pci_id.function = ACPI_PCI_FUNCTION (reg->address);
+ pci_register = (u16) ACPI_PCI_REGISTER (reg->address);
- acpi_os_write_pci_configuration (&pci_id, pci_register, value, width);
+ status = acpi_os_write_pci_configuration (&pci_id, pci_register,
+ (acpi_integer) value, width);
break;
+
+
+ default:
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
+ "Unsupported address space: %X\n", reg->address_space_id));
+ return (AE_BAD_PARAMETER);
}
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_IO, "Wrote: %8.8X width %2d to %8.8X%8.8X (%s)\n",
+ value, width,
+ ACPI_HIDWORD (reg->address),
+ ACPI_LODWORD (reg->address),
+ acpi_ut_get_region_name (reg->address_space_id)));
+
+ return (status);
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)