summaryrefslogtreecommitdiffstats
path: root/drivers/acpi/hardware/hwregs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/hardware/hwregs.c')
-rw-r--r--drivers/acpi/hardware/hwregs.c875
1 files changed, 621 insertions, 254 deletions
diff --git a/drivers/acpi/hardware/hwregs.c b/drivers/acpi/hardware/hwregs.c
index 2ab4b1d95..77b6a1c8c 100644
--- a/drivers/acpi/hardware/hwregs.c
+++ b/drivers/acpi/hardware/hwregs.c
@@ -3,7 +3,7 @@
*
* Module Name: hwregs - Read/write access functions for the various ACPI
* control and status registers.
- * $Revision: 67 $
+ * $Revision: 86 $
*
******************************************************************************/
@@ -36,8 +36,8 @@
/* This matches the #defines in actypes.h. */
-NATIVE_CHAR *sleep_state_table[] = {"\\_S0_","\\_S1_","\\_S2_","\\_S3_",
- "\\_S4_","\\_S4_b","\\_S5_"};
+NATIVE_CHAR *sleep_state_table[] = {"\\_S0_","\\_S1_","\\_S2_","\\_S3_",
+ "\\_S4_","\\_S4_b","\\_S5_"};
/*******************************************************************************
@@ -53,7 +53,7 @@ NATIVE_CHAR *sleep_state_table[] = {"\\_S0_","\\_S1_","\\_S2_","\\_S3_",
*
******************************************************************************/
-u32
+static u32
acpi_hw_get_bit_shift (
u32 mask)
{
@@ -87,28 +87,31 @@ acpi_hw_clear_acpi_status (void)
acpi_cm_acquire_mutex (ACPI_MTX_HARDWARE);
- acpi_os_out16 (acpi_gbl_FACP->pm1a_evt_blk, (u16) ALL_FIXED_STS_BITS);
+ acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, PM1_STS, ALL_FIXED_STS_BITS);
+
- if (acpi_gbl_FACP->pm1b_evt_blk) {
- acpi_os_out16 ((u16) acpi_gbl_FACP->pm1b_evt_blk,
+ if (ACPI_VALID_ADDRESS (acpi_gbl_FADT->Xpm1b_evt_blk.address)) {
+ acpi_os_out16 ((ACPI_IO_ADDRESS) ACPI_GET_ADDRESS (acpi_gbl_FADT->Xpm1b_evt_blk.address),
(u16) ALL_FIXED_STS_BITS);
}
/* now clear the GPE Bits */
- if (acpi_gbl_FACP->gpe0blk_len) {
- gpe_length = (u16) DIV_2 (acpi_gbl_FACP->gpe0blk_len);
+ if (acpi_gbl_FADT->gpe0blk_len) {
+ gpe_length = (u16) DIV_2 (acpi_gbl_FADT->gpe0blk_len);
for (index = 0; index < gpe_length; index++) {
- acpi_os_out8 ((acpi_gbl_FACP->gpe0blk + index), (u8) 0xff);
+ acpi_os_out8 ((ACPI_IO_ADDRESS) (ACPI_GET_ADDRESS (acpi_gbl_FADT->Xgpe0blk.address) + index),
+ (u8) 0xff);
}
}
- if (acpi_gbl_FACP->gpe1_blk_len) {
- gpe_length = (u16) DIV_2 (acpi_gbl_FACP->gpe1_blk_len);
+ if (acpi_gbl_FADT->gpe1_blk_len) {
+ gpe_length = (u16) DIV_2 (acpi_gbl_FADT->gpe1_blk_len);
for (index = 0; index < gpe_length; index++) {
- acpi_os_out8 ((acpi_gbl_FACP->gpe1_blk + index), (u8) 0xff);
+ acpi_os_out8 ((ACPI_IO_ADDRESS) (ACPI_GET_ADDRESS (acpi_gbl_FADT->Xgpe1_blk.address) + index),
+ (u8) 0xff);
}
}
@@ -162,7 +165,7 @@ acpi_hw_obtain_sleep_type_register_data (
}
if (!obj_desc) {
- REPORT_ERROR ("Missing Sleep State object");
+ REPORT_ERROR (("Missing Sleep State object\n"));
return (AE_NOT_EXIST);
}
@@ -172,17 +175,12 @@ acpi_hw_obtain_sleep_type_register_data (
* two elements
*/
- if (obj_desc->common.type != ACPI_TYPE_PACKAGE) {
- /* Must be a package */
-
- REPORT_ERROR ("Sleep State object is not of type Package");
- status = AE_ERROR;
- }
+ status = acpi_cm_resolve_package_references(obj_desc);
- else if (obj_desc->package.count < 2) {
+ if (obj_desc->package.count < 2) {
/* Must have at least two elements */
- REPORT_ERROR ("Sleep State package does not have at least two elements");
+ REPORT_ERROR (("Sleep State package does not have at least two elements\n"));
status = AE_ERROR;
}
@@ -193,7 +191,7 @@ acpi_hw_obtain_sleep_type_register_data (
{
/* Must have two */
- REPORT_ERROR ("Sleep State package elements are not both of type Number");
+ REPORT_ERROR (("Sleep State package elements are not both of type Number\n"));
status = AE_ERROR;
}
@@ -216,23 +214,23 @@ acpi_hw_obtain_sleep_type_register_data (
/*******************************************************************************
*
- * FUNCTION: Acpi_hw_register_access
+ * FUNCTION: Acpi_hw_register_bit_access
*
* PARAMETERS: Read_write - Either ACPI_READ or ACPI_WRITE.
* Use_lock - Lock the hardware
- * Register_id - index of ACPI register to access
+ * Register_id - index of ACPI Register to access
* Value - (only used on write) value to write to the
- * register. Shifted all the way right.
+ * Register. Shifted all the way right.
*
- * RETURN: Value written to or read from specified register. This value
+ * RETURN: Value written to or read from specified Register. This value
* is shifted all the way right.
*
- * DESCRIPTION: Generic ACPI register read/write function.
+ * DESCRIPTION: Generic ACPI Register read/write function.
*
******************************************************************************/
u32
-acpi_hw_register_access (
+acpi_hw_register_bit_access (
NATIVE_UINT read_write,
u8 use_lock,
u32 register_id,
@@ -241,7 +239,6 @@ acpi_hw_register_access (
u32 register_value = 0;
u32 mask = 0;
u32 value = 0;
- ACPI_IO_ADDRESS gpe_reg = 0;
if (read_write == ACPI_WRITE) {
@@ -252,183 +249,125 @@ acpi_hw_register_access (
va_end (marker);
}
- /*
- * TBD: [Restructure] May want to split the Acpi_event code and the
- * Control code
- */
+ if (ACPI_MTX_LOCK == use_lock) {
+ acpi_cm_acquire_mutex (ACPI_MTX_HARDWARE);
+ }
/*
* 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_id & REGISTER_BLOCK_MASK)
+ switch (REGISTER_BLOCK_ID(register_id))
{
- case PM1_EVT:
-
- if (register_id < TMR_EN) {
- /* status register */
-
- if (ACPI_MTX_LOCK == use_lock) {
- acpi_cm_acquire_mutex (ACPI_MTX_HARDWARE);
- }
-
+ case PM1_STS:
- register_value = (u32) acpi_os_in16 (acpi_gbl_FACP->pm1a_evt_blk);
- if (acpi_gbl_FACP->pm1b_evt_blk) {
- register_value |= (u32) acpi_os_in16 (acpi_gbl_FACP->pm1b_evt_blk);
- }
-
- switch (register_id)
- {
- case TMR_STS:
- mask = TMR_STS_MASK;
- break;
-
- case BM_STS:
- mask = BM_STS_MASK;
- break;
+ switch (register_id)
+ {
+ case TMR_STS:
+ mask = TMR_STS_MASK;
+ break;
- case GBL_STS:
- mask = GBL_STS_MASK;
- break;
+ case BM_STS:
+ mask = BM_STS_MASK;
+ break;
- case PWRBTN_STS:
- mask = PWRBTN_STS_MASK;
- break;
+ case GBL_STS:
+ mask = GBL_STS_MASK;
+ break;
- case SLPBTN_STS:
- mask = SLPBTN_STS_MASK;
- break;
+ case PWRBTN_STS:
+ mask = PWRBTN_STS_MASK;
+ break;
- case RTC_STS:
- mask = RTC_STS_MASK;
- break;
+ case SLPBTN_STS:
+ mask = SLPBTN_STS_MASK;
+ break;
- case WAK_STS:
- mask = WAK_STS_MASK;
- break;
+ case RTC_STS:
+ mask = RTC_STS_MASK;
+ break;
- default:
- mask = 0;
- break;
- }
+ case WAK_STS:
+ mask = WAK_STS_MASK;
+ break;
- 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
- */
+ default:
+ mask = 0;
+ break;
+ }
- value <<= acpi_hw_get_bit_shift (mask);
- value &= mask;
+ register_value = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, PM1_STS);
- if (value) {
- acpi_os_out16 (acpi_gbl_FACP->pm1a_evt_blk, (u16) value);
+ 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
+ */
- if (acpi_gbl_FACP->pm1b_evt_blk) {
- acpi_os_out16 (acpi_gbl_FACP->pm1b_evt_blk, (u16) value);
- }
+ value <<= acpi_hw_get_bit_shift (mask);
+ value &= mask;
- register_value = 0;
- }
- }
+ if (value) {
+ acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, PM1_STS, (u16) value);
- if (ACPI_MTX_LOCK == use_lock) {
- acpi_cm_release_mutex (ACPI_MTX_HARDWARE);
+ register_value = 0;
}
}
- else {
- /* enable register */
-
- if (ACPI_MTX_LOCK == use_lock) {
- acpi_cm_acquire_mutex (ACPI_MTX_HARDWARE);
- }
-
- register_value = (u32) acpi_os_in16 (acpi_gbl_FACP->pm1a_evt_blk +
- DIV_2 (acpi_gbl_FACP->pm1_evt_len));
-
- if (acpi_gbl_FACP->pm1b_evt_blk) {
- register_value |= (u32) acpi_os_in16 (acpi_gbl_FACP->pm1b_evt_blk +
- DIV_2 (acpi_gbl_FACP->pm1_evt_len));
+ break;
- }
- switch (register_id)
- {
- case TMR_EN:
- mask = TMR_EN_MASK;
- break;
+ case PM1_EN:
- case GBL_EN:
- mask = GBL_EN_MASK;
- break;
+ switch (register_id)
+ {
+ case TMR_EN:
+ mask = TMR_EN_MASK;
+ break;
- case PWRBTN_EN:
- mask = PWRBTN_EN_MASK;
- break;
+ case GBL_EN:
+ mask = GBL_EN_MASK;
+ break;
- case SLPBTN_EN:
- mask = SLPBTN_EN_MASK;
- break;
+ case PWRBTN_EN:
+ mask = PWRBTN_EN_MASK;
+ break;
- case RTC_EN:
- mask = RTC_EN_MASK;
- break;
+ case SLPBTN_EN:
+ mask = SLPBTN_EN_MASK;
+ break;
- default:
- mask = 0;
- break;
- }
+ case RTC_EN:
+ mask = RTC_EN_MASK;
+ break;
- if (read_write == ACPI_WRITE) {
- register_value &= ~mask;
- value <<= acpi_hw_get_bit_shift (mask);
- value &= mask;
- register_value |= value;
-
- acpi_os_out16 ((acpi_gbl_FACP->pm1a_evt_blk +
- DIV_2 (acpi_gbl_FACP->pm1_evt_len)),
- (u16) register_value);
-
- if (acpi_gbl_FACP->pm1b_evt_blk) {
- acpi_os_out16 ((acpi_gbl_FACP->pm1b_evt_blk +
- DIV_2 (acpi_gbl_FACP->pm1_evt_len)),
- (u16) register_value);
- }
- }
- if(ACPI_MTX_LOCK == use_lock) {
- acpi_cm_release_mutex (ACPI_MTX_HARDWARE);
- }
+ default:
+ mask = 0;
+ break;
}
- break;
-
- case PM1_CONTROL:
+ register_value = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, PM1_EN);
- register_value = 0;
+ if (read_write == ACPI_WRITE) {
+ register_value &= ~mask;
+ value <<= acpi_hw_get_bit_shift (mask);
+ value &= mask;
+ register_value |= value;
- if (ACPI_MTX_LOCK == use_lock) {
- acpi_cm_acquire_mutex (ACPI_MTX_HARDWARE);
+ acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, PM1_EN, (u16) register_value);
}
- if (register_id != SLP_TYPE_B) {
- /*
- * SLP_TYPx 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
- */
+ break;
- register_value = (u32) acpi_os_in16 (acpi_gbl_FACP->pm1a_cnt_blk);
- }
- if (acpi_gbl_FACP->pm1b_cnt_blk && register_id != (u32) SLP_TYPE_A) {
- register_value |= (u32) acpi_os_in16 (acpi_gbl_FACP->pm1b_cnt_blk);
- }
+ case PM1_CONTROL:
switch (register_id)
{
@@ -458,6 +397,14 @@ acpi_hw_register_access (
break;
}
+
+ /*
+ * Read 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.
+ */
+ register_value = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, PM1_CONTROL);
+
if (read_write == ACPI_WRITE) {
register_value &= ~mask;
value <<= acpi_hw_get_bit_shift (mask);
@@ -465,47 +412,23 @@ acpi_hw_register_access (
register_value |= value;
/*
- * SLP_TYPE_x registers are written differently
- * than any other control registers with
- * respect to A and B registers. The 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.
*/
- if (register_id != SLP_TYPE_B) {
- if (mask == SLP_EN_MASK) {
- disable(); /* disable interrupts */
- }
-
- acpi_os_out16 (acpi_gbl_FACP->pm1a_cnt_blk, (u16) register_value);
-
- if (mask == SLP_EN_MASK) {
- /*
- * Enable interrupts, the SCI handler is likely going to
- * be invoked as soon as interrupts are enabled, since gpe's
- * and most fixed resume events also generate SCI's.
- */
- enable();
- }
- }
-
- if (acpi_gbl_FACP->pm1b_cnt_blk && register_id != (u32) SLP_TYPE_A) {
- acpi_os_out16 (acpi_gbl_FACP->pm1b_cnt_blk, (u16) register_value);
- }
- }
-
- if (ACPI_MTX_LOCK == use_lock) {
- acpi_cm_release_mutex (ACPI_MTX_HARDWARE);
+ acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK,
+ register_id, (u16) register_value);
}
break;
case PM2_CONTROL:
- if (ACPI_MTX_LOCK == use_lock) {
- acpi_cm_acquire_mutex (ACPI_MTX_HARDWARE);
- }
-
- register_value = (u32) acpi_os_in16 (acpi_gbl_FACP->pm2_cnt_blk);
switch (register_id)
{
case ARB_DIS:
@@ -517,85 +440,64 @@ acpi_hw_register_access (
break;
}
+ register_value = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, PM2_CONTROL);
+
if (read_write == ACPI_WRITE) {
register_value &= ~mask;
value <<= acpi_hw_get_bit_shift (mask);
value &= mask;
register_value |= value;
- acpi_os_out16 (acpi_gbl_FACP->pm2_cnt_blk, (u16) register_value);
- }
-
- if (ACPI_MTX_LOCK == use_lock) {
- acpi_cm_release_mutex (ACPI_MTX_HARDWARE);
+ acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK,
+ PM2_CONTROL, (u8) (register_value));
}
break;
case PM_TIMER:
- register_value = acpi_os_in32 (acpi_gbl_FACP->pm_tmr_blk);
- mask = 0xFFFFFFFF;
+ mask = TMR_VAL_MASK;
+ register_value = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK,
+ PM_TIMER);
break;
case GPE1_EN_BLOCK:
-
- gpe_reg = (acpi_gbl_FACP->gpe1_blk + acpi_gbl_FACP->gpe1_base) +
- (gpe_reg + (DIV_2 (acpi_gbl_FACP->gpe1_blk_len)));
-
-
case GPE1_STS_BLOCK:
-
- if (!gpe_reg) {
- gpe_reg = (acpi_gbl_FACP->gpe1_blk + acpi_gbl_FACP->gpe1_base);
- }
-
-
case GPE0_EN_BLOCK:
-
- if (!gpe_reg) {
- gpe_reg = acpi_gbl_FACP->gpe0blk + DIV_2 (acpi_gbl_FACP->gpe0blk_len);
- }
-
-
case GPE0_STS_BLOCK:
- if (!gpe_reg) {
- gpe_reg = acpi_gbl_FACP->gpe0blk;
- }
-
- /* Determine the bit to be accessed */
+ /* 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 = (((u32) register_id) & BIT_IN_REGISTER_MASK);
- mask = 1 << (mask-1);
+ 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
+ * 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
+ * the Register indicated in Mask to a 1, all others are 0
*/
- if (mask > LOW_BYTE) {
- /* Shift the value 1 byte to the right and add 1 to the register */
-
- mask >>= ONE_BYTE;
- gpe_reg++;
- }
-
/* Now get the current Enable Bits in the selected Reg */
- if(ACPI_MTX_LOCK == use_lock) {
- acpi_cm_acquire_mutex (ACPI_MTX_HARDWARE);
- }
-
- register_value = (u32) acpi_os_in8 (gpe_reg);
+ register_value = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, register_id);
if (read_write == ACPI_WRITE) {
register_value &= ~mask;
value <<= acpi_hw_get_bit_shift (mask);
@@ -603,29 +505,494 @@ acpi_hw_register_access (
register_value |= value;
/* This write will put the Action state into the General Purpose */
-
/* Enable Register indexed by the value in Mask */
- acpi_os_out8 (gpe_reg, (u8) register_value);
- register_value = (u32) acpi_os_in8 (gpe_reg);
- }
-
- if(ACPI_MTX_LOCK == use_lock) {
- acpi_cm_release_mutex (ACPI_MTX_HARDWARE);
+ 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);
}
break;
+ case SMI_CMD_BLOCK:
case PROCESSOR_BLOCK:
+ /* not used */
default:
mask = 0;
break;
}
+ if (ACPI_MTX_LOCK == use_lock) {
+ acpi_cm_release_mutex (ACPI_MTX_HARDWARE);
+ }
+
register_value &= mask;
register_value >>= acpi_hw_get_bit_shift (mask);
return (register_value);
}
+
+
+/******************************************************************************
+ *
+ * FUNCTION: Acpi_hw_register_read
+ *
+ * PARAMETERS: Use_lock - Mutex hw access.
+ * Register_id - Register_iD + Offset.
+ *
+ * RETURN: Value read or written.
+ *
+ * DESCRIPTION: Acpi register read function. Registers are read at the
+ * given offset.
+ *
+ ******************************************************************************/
+
+u32
+acpi_hw_register_read (
+ u8 use_lock,
+ u32 register_id)
+{
+ u32 value = 0;
+ u32 bank_offset;
+
+ if (ACPI_MTX_LOCK == use_lock) {
+ acpi_cm_acquire_mutex (ACPI_MTX_HARDWARE);
+ }
+
+
+ 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;
+
+
+ case PM1_EN: /* 16-bit access*/
+
+ 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);
+ break;
+
+
+ case PM1_CONTROL: /* 16-bit access */
+
+ if (register_id != SLP_TYPE_B) {
+ value |= acpi_hw_low_level_read (16, &acpi_gbl_FADT->Xpm1a_cnt_blk, 0);
+ }
+
+ if (register_id != SLP_TYPE_A) {
+ value |= acpi_hw_low_level_read (16, &acpi_gbl_FADT->Xpm1b_cnt_blk, 0);
+ }
+ break;
+
+
+ case PM2_CONTROL: /* 8-bit access */
+
+ value = acpi_hw_low_level_read (8, &acpi_gbl_FADT->Xpm2_cnt_blk, 0);
+ break;
+
+
+ case PM_TIMER: /* 32-bit access */
+
+ value = acpi_hw_low_level_read (32, &acpi_gbl_FADT->Xpm_tmr_blk, 0);
+ break;
+
+
+ case GPE0_STS_BLOCK: /* 8-bit access */
+
+ value = acpi_hw_low_level_read (8, &acpi_gbl_FADT->Xgpe0blk, 0);
+ break;
+
+
+ case GPE0_EN_BLOCK: /* 8-bit access */
+
+ bank_offset = DIV_2 (acpi_gbl_FADT->gpe0blk_len);
+ value = acpi_hw_low_level_read (8, &acpi_gbl_FADT->Xgpe0blk, bank_offset);
+ break;
+
+
+ case GPE1_STS_BLOCK: /* 8-bit access */
+
+ value = acpi_hw_low_level_read (8, &acpi_gbl_FADT->Xgpe1_blk, 0);
+ break;
+
+
+ case GPE1_EN_BLOCK: /* 8-bit access */
+
+ bank_offset = DIV_2 (acpi_gbl_FADT->gpe1_blk_len);
+ value = acpi_hw_low_level_read (8, &acpi_gbl_FADT->Xgpe1_blk, bank_offset);
+ break;
+
+
+ case SMI_CMD_BLOCK: /* 8bit */
+
+ value = (u32) acpi_os_in8 (acpi_gbl_FADT->smi_cmd);
+ break;
+
+
+ default:
+ value = 0;
+ break;
+ }
+
+
+ if (ACPI_MTX_LOCK == use_lock) {
+ acpi_cm_release_mutex (ACPI_MTX_HARDWARE);
+ }
+
+ return (value);
+}
+
+
+/******************************************************************************
+ *
+ * FUNCTION: Acpi_hw_register_write
+ *
+ * PARAMETERS: Use_lock - Mutex hw access.
+ * Register_id - Register_iD + Offset.
+ *
+ * RETURN: Value read or written.
+ *
+ * DESCRIPTION: Acpi register Write function. Registers are written at the
+ * given offset.
+ *
+ ******************************************************************************/
+
+void
+acpi_hw_register_write (
+ u8 use_lock,
+ u32 register_id,
+ u32 value)
+{
+ u32 bank_offset;
+
+
+ if (ACPI_MTX_LOCK == use_lock) {
+ acpi_cm_acquire_mutex (ACPI_MTX_HARDWARE);
+ }
+
+
+ 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;
+
+
+ case PM1_CONTROL: /* 16-bit access */
+
+ /*
+ * If SLP_TYP_A or SLP_TYP_B, only write to one reg block.
+ * Otherwise, write to both.
+ */
+ if (register_id == SLP_TYPE_A) {
+ acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1a_cnt_blk, 0);
+ }
+ else if (register_id == SLP_TYPE_B) {
+ acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1b_cnt_blk, 0);
+ }
+ else {
+ /* disable/re-enable interrupts if sleeping */
+ if (register_id == SLP_EN) {
+ disable();
+ }
+
+ 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);
+
+ if (register_id == SLP_EN) {
+ enable();
+ }
+ }
+
+ break;
+
+
+ case PM2_CONTROL: /* 8-bit access */
+
+ acpi_hw_low_level_write (8, value, &acpi_gbl_FADT->Xpm2_cnt_blk, 0);
+ break;
+
+
+ case PM_TIMER: /* 32-bit access */
+
+ acpi_hw_low_level_write (32, value, &acpi_gbl_FADT->Xpm_tmr_blk, 0);
+ break;
+
+
+ case GPE0_STS_BLOCK: /* 8-bit access */
+
+ acpi_hw_low_level_write (8, value, &acpi_gbl_FADT->Xgpe0blk, 0);
+ break;
+
+
+ case GPE0_EN_BLOCK: /* 8-bit access */
+
+ bank_offset = DIV_2 (acpi_gbl_FADT->gpe0blk_len);
+ acpi_hw_low_level_write (8, value, &acpi_gbl_FADT->Xgpe0blk, bank_offset);
+ break;
+
+
+ case GPE1_STS_BLOCK: /* 8-bit access */
+
+ acpi_hw_low_level_write (8, value, &acpi_gbl_FADT->Xgpe1_blk, 0);
+ break;
+
+
+ case GPE1_EN_BLOCK: /* 8-bit access */
+
+ bank_offset = DIV_2 (acpi_gbl_FADT->gpe1_blk_len);
+ acpi_hw_low_level_write (8, value, &acpi_gbl_FADT->Xgpe1_blk, bank_offset);
+ break;
+
+
+ case SMI_CMD_BLOCK: /* 8bit */
+
+ /* For 2.0, SMI_CMD is always in IO space */
+ /* TBD: what about 1.0? 0.71? */
+
+ acpi_os_out8 (acpi_gbl_FADT->smi_cmd, (u8) value);
+ break;
+
+
+ default:
+ value = 0;
+ break;
+ }
+
+
+ if (ACPI_MTX_LOCK == use_lock) {
+ acpi_cm_release_mutex (ACPI_MTX_HARDWARE);
+ }
+
+ return;
+}
+
+
+/******************************************************************************
+ *
+ * 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
+ *
+ * RETURN: Value read
+ *
+ * DESCRIPTION: Read from either memory, IO, or PCI config space.
+ *
+ ******************************************************************************/
+
+u32
+acpi_hw_low_level_read (
+ u32 width,
+ ACPI_GAS *reg,
+ u32 offset)
+{
+ u32 value = 0;
+ ACPI_PHYSICAL_ADDRESS mem_address;
+ ACPI_IO_ADDRESS io_address;
+ u32 pci_register;
+ u32 pci_dev_func;
+
+
+ /*
+ * Must have a valid pointer to a GAS structure, and
+ * a non-zero address within
+ */
+ if ((!reg) ||
+ (!ACPI_VALID_ADDRESS (reg->address)))
+ {
+ return 0;
+ }
+
+
+ /*
+ * Three address spaces supported:
+ * Memory, Io, or PCI config.
+ */
+
+ switch (reg->address_space_id)
+ {
+ case ADDRESS_SPACE_SYSTEM_MEMORY:
+
+ mem_address = (ACPI_PHYSICAL_ADDRESS) (ACPI_GET_ADDRESS (reg->address) + offset);
+
+ switch (width)
+ {
+ case 8:
+ value = acpi_os_mem_in8 (mem_address);
+ break;
+ case 16:
+ value = acpi_os_mem_in16 (mem_address);
+ break;
+ case 32:
+ value = acpi_os_mem_in32 (mem_address);
+ break;
+ }
+ break;
+
+
+ case ADDRESS_SPACE_SYSTEM_IO:
+
+ io_address = (ACPI_IO_ADDRESS) (ACPI_GET_ADDRESS (reg->address) + offset);
+
+ switch (width)
+ {
+ case 8:
+ value = acpi_os_in8 (io_address);
+ break;
+ case 16:
+ value = acpi_os_in16 (io_address);
+ break;
+ case 32:
+ value = acpi_os_in32 (io_address);
+ break;
+ }
+ break;
+
+
+ case ADDRESS_SPACE_PCI_CONFIG:
+
+ pci_dev_func = ACPI_PCI_DEVFUN (ACPI_GET_ADDRESS (reg->address));
+ pci_register = ACPI_PCI_REGISTER (ACPI_GET_ADDRESS (reg->address)) + offset;
+
+ switch (width)
+ {
+ case 8:
+ acpi_os_read_pci_cfg_byte (0, pci_dev_func, pci_register, (u8 *) &value);
+ break;
+ case 16:
+ acpi_os_read_pci_cfg_word (0, pci_dev_func, pci_register, (u16 *) &value);
+ break;
+ case 32:
+ acpi_os_read_pci_cfg_dword (0, pci_dev_func, pci_register, (u32 *) &value);
+ break;
+ }
+ break;
+ }
+
+ return value;
+}
+
+
+/******************************************************************************
+ *
+ * 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
+ *
+ * DESCRIPTION: Read from either memory, IO, or PCI config space.
+ *
+ ******************************************************************************/
+
+void
+acpi_hw_low_level_write (
+ u32 width,
+ u32 value,
+ ACPI_GAS *reg,
+ u32 offset)
+{
+ ACPI_PHYSICAL_ADDRESS mem_address;
+ ACPI_IO_ADDRESS io_address;
+ u32 pci_register;
+ u32 pci_dev_func;
+
+
+ /*
+ * Must have a valid pointer to a GAS structure, and
+ * a non-zero address within
+ */
+ if ((!reg) ||
+ (!ACPI_VALID_ADDRESS (reg->address)))
+ {
+ return;
+ }
+
+
+ /*
+ * Three address spaces supported:
+ * Memory, Io, or PCI config.
+ */
+
+ switch (reg->address_space_id)
+ {
+ case ADDRESS_SPACE_SYSTEM_MEMORY:
+
+ mem_address = (ACPI_PHYSICAL_ADDRESS) (ACPI_GET_ADDRESS (reg->address) + offset);
+
+ switch (width)
+ {
+ case 8:
+ acpi_os_mem_out8 (mem_address, (u8) value);
+ break;
+ case 16:
+ acpi_os_mem_out16 (mem_address, (u16) value);
+ break;
+ case 32:
+ acpi_os_mem_out32 (mem_address, (u32) value);
+ break;
+ }
+ break;
+
+
+ case ADDRESS_SPACE_SYSTEM_IO:
+
+ io_address = (ACPI_IO_ADDRESS) (ACPI_GET_ADDRESS (reg->address) + offset);
+
+ switch (width)
+ {
+ case 8:
+ acpi_os_out8 (io_address, (u8) value);
+ break;
+ case 16:
+ acpi_os_out16 (io_address, (u16) value);
+ break;
+ case 32:
+ acpi_os_out32 (io_address, (u32) value);
+ break;
+ }
+ break;
+
+
+ case ADDRESS_SPACE_PCI_CONFIG:
+
+ pci_dev_func = ACPI_PCI_DEVFUN (ACPI_GET_ADDRESS (reg->address));
+ pci_register = ACPI_PCI_REGISTER (ACPI_GET_ADDRESS (reg->address)) + offset;
+
+ switch (width)
+ {
+ case 8:
+ acpi_os_write_pci_cfg_byte (0, pci_dev_func, pci_register, (u8) value);
+ break;
+ case 16:
+ acpi_os_write_pci_cfg_word (0, pci_dev_func, pci_register, (u16) value);
+ break;
+ case 32:
+ acpi_os_write_pci_cfg_dword (0, pci_dev_func, pci_register, (u32) value);
+ break;
+ }
+ break;
+ }
+}