WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-unstable] x86 ACPI sleep: Fix a bug when ACPI regis

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] x86 ACPI sleep: Fix a bug when ACPI registers in System_Memory
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Thu, 20 Mar 2008 05:41:05 -0700
Delivery-date: Thu, 20 Mar 2008 05:45:48 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1205922793 0
# Node ID 26a7a2d154e1a0f51da1fd44337091f3bcf39bf9
# Parent  70f9a2110421cc6f4ce066eb80d4c639a28643bd
x86 ACPI sleep: Fix a bug when ACPI registers in System_Memory

Some ACPI registers may be in System_Memory but not System_IO space,
For these machines S3 fails since current Xen use I/O instructions (e.g.
inb(), outb(), etc.) to access ACPI registers. The patch attached fix
the bug by adding GAS (generic address structure) support ported from
Linux, which should also benefit later ACPI activity within Xen.

Signed-off-by: Huacai Chen <huacai.chen@xxxxxxxxx>
---
 xen/arch/x86/acpi/boot.c   |   72 ++++----
 xen/arch/x86/acpi/power.c  |   31 ++-
 xen/drivers/acpi/Makefile  |    2 
 xen/drivers/acpi/hwregs.c  |  385 +++++++++++++++++++++++++++++++++++++++++++++
 xen/drivers/acpi/osl.c     |  183 +++++++++++++++++++++
 xen/include/asm-x86/acpi.h |   10 -
 6 files changed, 639 insertions(+), 44 deletions(-)

diff -r 70f9a2110421 -r 26a7a2d154e1 xen/arch/x86/acpi/boot.c
--- a/xen/arch/x86/acpi/boot.c  Wed Mar 19 10:22:49 2008 +0000
+++ b/xen/arch/x86/acpi/boot.c  Wed Mar 19 10:33:13 2008 +0000
@@ -349,10 +349,10 @@ static int __init acpi_parse_hpet(unsign
        }
 
 #if 0/*def     CONFIG_X86_64*/
-        vxtime.hpet_address = hpet_tbl->address.address;
-
-        printk(KERN_INFO PREFIX "HPET id: %#x base: %#lx\n",
-               hpet_tbl->id, vxtime.hpet_address);
+       vxtime.hpet_address = hpet_tbl->address.address;
+
+       printk(KERN_INFO PREFIX "HPET id: %#x base: %#lx\n",
+              hpet_tbl->id, vxtime.hpet_address);
 #else  /* X86 */
        {
                extern unsigned long hpet_address;
@@ -389,31 +389,36 @@ acpi_fadt_parse_sleep_info(struct acpi_t
        rsdp = __va(rsdp_phys);
 
        if (fadt->header.revision >= FADT2_REVISION_ID) {
-               /* Sanity check on FADT Rev. 2 */
-               if ((fadt->xpm1a_control_block.space_id !=
-                    ACPI_ADR_SPACE_SYSTEM_IO) ||
-                   (fadt->xpm1b_control_block.space_id !=
-                    ACPI_ADR_SPACE_SYSTEM_IO) ||
-                   (fadt->xpm1a_event_block.space_id !=
-                    ACPI_ADR_SPACE_SYSTEM_IO) ||
-                   (fadt->xpm1b_event_block.space_id !=
-                    ACPI_ADR_SPACE_SYSTEM_IO))
-                       goto bad; 
-
-               acpi_sinfo.pm1a_cnt = 
(uint16_t)fadt->xpm1a_control_block.address;
-               acpi_sinfo.pm1b_cnt = 
(uint16_t)fadt->xpm1b_control_block.address;
-               acpi_sinfo.pm1a_evt = (uint16_t)fadt->xpm1a_event_block.address;
-               acpi_sinfo.pm1b_evt = (uint16_t)fadt->xpm1b_event_block.address;
-       }
-
-       if (!acpi_sinfo.pm1a_cnt)
-               acpi_sinfo.pm1a_cnt = (uint16_t)fadt->pm1a_control_block;
-       if (!acpi_sinfo.pm1b_cnt)
-               acpi_sinfo.pm1b_cnt = (uint16_t)fadt->pm1b_control_block;
-       if (!acpi_sinfo.pm1a_evt)
-               acpi_sinfo.pm1a_evt = (uint16_t)fadt->pm1a_event_block;
-       if (!acpi_sinfo.pm1b_evt)
-               acpi_sinfo.pm1b_evt = (uint16_t)fadt->pm1b_event_block;
+               memcpy(&acpi_sinfo.pm1a_cnt_blk, &fadt->xpm1a_control_block,
+                       sizeof(struct acpi_generic_address));
+               memcpy(&acpi_sinfo.pm1b_cnt_blk, &fadt->xpm1b_control_block,
+                       sizeof(struct acpi_generic_address));
+               memcpy(&acpi_sinfo.pm1a_evt_blk, &fadt->xpm1a_event_block,
+                       sizeof(struct acpi_generic_address));
+               memcpy(&acpi_sinfo.pm1b_evt_blk, &fadt->xpm1b_event_block,
+                       sizeof(struct acpi_generic_address));
+       } else {
+               acpi_sinfo.pm1a_cnt_blk.address = fadt->pm1a_control_block;
+               acpi_sinfo.pm1b_cnt_blk.address = fadt->pm1b_control_block;
+               acpi_sinfo.pm1a_evt_blk.address = fadt->pm1a_event_block;
+               acpi_sinfo.pm1b_evt_blk.address = fadt->pm1b_event_block;
+               acpi_sinfo.pm1a_cnt_blk.space_id = ACPI_ADR_SPACE_SYSTEM_IO;
+               acpi_sinfo.pm1b_cnt_blk.space_id = ACPI_ADR_SPACE_SYSTEM_IO;
+               acpi_sinfo.pm1a_evt_blk.space_id = ACPI_ADR_SPACE_SYSTEM_IO;
+               acpi_sinfo.pm1b_evt_blk.space_id = ACPI_ADR_SPACE_SYSTEM_IO;
+               acpi_sinfo.pm1a_cnt_blk.bit_width = 16;
+               acpi_sinfo.pm1b_cnt_blk.bit_width = 16;
+               acpi_sinfo.pm1a_evt_blk.bit_width = 16;
+               acpi_sinfo.pm1b_evt_blk.bit_width = 16;
+               acpi_sinfo.pm1a_cnt_blk.bit_offset = 0;
+               acpi_sinfo.pm1b_cnt_blk.bit_offset = 0;
+               acpi_sinfo.pm1a_evt_blk.bit_offset = 0;
+               acpi_sinfo.pm1b_evt_blk.bit_offset = 0;
+               acpi_sinfo.pm1a_cnt_blk.access_width = 0;
+               acpi_sinfo.pm1b_cnt_blk.access_width = 0;
+               acpi_sinfo.pm1a_evt_blk.access_width = 0;
+               acpi_sinfo.pm1b_evt_blk.access_width = 0;
+       }
 
        /* Now FACS... */
        if (fadt->header.revision >= FADT2_REVISION_ID)
@@ -456,9 +461,12 @@ acpi_fadt_parse_sleep_info(struct acpi_t
        }
 
        printk(KERN_INFO PREFIX
-              "ACPI SLEEP INFO: pm1x_cnt[%x,%x], pm1x_evt[%x,%x]\n",
-              acpi_sinfo.pm1a_cnt, acpi_sinfo.pm1b_cnt,
-              acpi_sinfo.pm1a_evt, acpi_sinfo.pm1b_cnt);
+              "ACPI SLEEP INFO: pm1x_cnt[%"PRIx64",%"PRIx64"], "
+              "pm1x_evt[%"PRIx64",%"PRIx64"]\n",
+              acpi_sinfo.pm1a_cnt_blk.address,
+              acpi_sinfo.pm1b_cnt_blk.address,
+              acpi_sinfo.pm1a_evt_blk.address,
+              acpi_sinfo.pm1b_evt_blk.address);
        printk(KERN_INFO PREFIX
               "                 wakeup_vec[%"PRIx64"], vec_size[%x]\n",
               acpi_sinfo.wakeup_vector, acpi_sinfo.vector_width);
diff -r 70f9a2110421 -r 26a7a2d154e1 xen/arch/x86/acpi/power.c
--- a/xen/arch/x86/acpi/power.c Wed Mar 19 10:22:49 2008 +0000
+++ b/xen/arch/x86/acpi/power.c Wed Mar 19 10:33:13 2008 +0000
@@ -106,7 +106,7 @@ static void acpi_sleep_prepare(u32 state
             *(uint64_t *)wakeup_vector_va =
                 tboot_in_measured_env() ?
                 (uint64_t)g_tboot_shared->s3_tb_wakeup_entry :
-               (uint64_t)bootsym_phys(wakeup_start);
+                (uint64_t)bootsym_phys(wakeup_start);
     }
 }
 
@@ -198,7 +198,7 @@ static long enter_state_helper(void *dat
  */
 int acpi_enter_sleep(struct xenpf_enter_acpi_sleep *sleep)
 {
-    if ( !IS_PRIV(current->domain) || !acpi_sinfo.pm1a_cnt )
+    if ( !IS_PRIV(current->domain) || !acpi_sinfo.pm1a_cnt_blk.address )
         return -EPERM;
 
     /* Sanity check */
@@ -222,10 +222,14 @@ int acpi_enter_sleep(struct xenpf_enter_
 
 static int acpi_get_wake_status(void)
 {
-    uint16_t val;
+    uint32_t val;
+    acpi_status status;
 
     /* Wake status is the 15th bit of PM1 status register. (ACPI spec 3.0) */
-    val = inw(acpi_sinfo.pm1a_evt) | inw(acpi_sinfo.pm1b_evt);
+    status = acpi_hw_register_read(ACPI_REGISTER_PM1_STATUS, &val);
+    if ( ACPI_FAILURE(status) )
+        return 0;
+
     val &= ACPI_BITMASK_WAKE_STATUS;
     val >>= ACPI_BITPOSITION_WAKE_STATUS;
     return val;
@@ -243,7 +247,7 @@ static void tboot_sleep(u8 sleep_state)
        case ACPI_STATE_S3:
            shutdown_type = TB_SHUTDOWN_S3;
            g_tboot_shared->s3_k_wakeup_entry =
-              (uint32_t)bootsym_phys(wakeup_start);
+               (uint32_t)bootsym_phys(wakeup_start);
            break;
        case ACPI_STATE_S4:
            shutdown_type = TB_SHUTDOWN_S4;
@@ -261,6 +265,8 @@ static void tboot_sleep(u8 sleep_state)
 /* System is really put into sleep state by this stub */
 acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state)
 {
+    acpi_status status;
+
     if ( tboot_in_measured_env() )
     {
         tboot_sleep(sleep_state);
@@ -270,9 +276,18 @@ acpi_status asmlinkage acpi_enter_sleep_
 
     ACPI_FLUSH_CPU_CACHE();
 
-    outw((u16)acpi_sinfo.pm1a_cnt_val, acpi_sinfo.pm1a_cnt);
-    if ( acpi_sinfo.pm1b_cnt )
-        outw((u16)acpi_sinfo.pm1b_cnt_val, acpi_sinfo.pm1b_cnt);
+    status = acpi_hw_register_write(ACPI_REGISTER_PM1A_CONTROL, 
+                                    acpi_sinfo.pm1a_cnt_val);
+    if ( ACPI_FAILURE(status) )
+        return_ACPI_STATUS(AE_ERROR);
+
+    if ( acpi_sinfo.pm1b_cnt_blk.address )
+    {
+        status = acpi_hw_register_write(ACPI_REGISTER_PM1B_CONTROL, 
+                                        acpi_sinfo.pm1b_cnt_val);
+        if ( ACPI_FAILURE(status) )
+            return_ACPI_STATUS(AE_ERROR);
+    }
 
     /* Wait until we enter sleep state, and spin until we wake */
     while ( !acpi_get_wake_status() )
diff -r 70f9a2110421 -r 26a7a2d154e1 xen/drivers/acpi/Makefile
--- a/xen/drivers/acpi/Makefile Wed Mar 19 10:22:49 2008 +0000
+++ b/xen/drivers/acpi/Makefile Wed Mar 19 10:33:13 2008 +0000
@@ -1,2 +1,4 @@ obj-y += tables.o
 obj-y += tables.o
 obj-y += numa.o
+obj-y += hwregs.o
+obj-y += osl.o
diff -r 70f9a2110421 -r 26a7a2d154e1 xen/drivers/acpi/hwregs.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/drivers/acpi/hwregs.c Wed Mar 19 10:33:13 2008 +0000
@@ -0,0 +1,385 @@
+
+/*******************************************************************************
+ *
+ * Module Name: hwregs - Read/write access functions for the various ACPI
+ *                       control and status registers.
+ *
+ 
******************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2006, R. Byron Moore
+ * All rights reserved.
+ *
+ * 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 <asm/io.h>
+#include <xen/config.h>
+#include <xen/init.h>
+#include <xen/types.h>
+#include <xen/errno.h>
+#include <acpi/acpi.h>
+
+#define _COMPONENT          ACPI_HARDWARE
+ACPI_MODULE_NAME("hwregs")
+
+/******************************************************************************
+ *
+ * FUNCTION:    acpi_hw_register_read
+ *
+ * PARAMETERS:  register_id         - ACPI Register ID
+ *              return_value        - Where the register value is returned
+ *
+ * RETURN:      Status and the value read.
+ *
+ * DESCRIPTION: Read from the specified ACPI register
+ *
+ 
******************************************************************************/
+acpi_status
+acpi_hw_register_read(u32 register_id, u32 * return_value)
+{
+       u32 value1 = 0;
+       u32 value2 = 0;
+       acpi_status status;
+
+       ACPI_FUNCTION_TRACE(hw_register_read);
+
+       switch (register_id) {
+       case ACPI_REGISTER_PM1_STATUS:  /* 16-bit access */
+
+               status =
+                   acpi_hw_low_level_read(16, &value1,
+                                          &acpi_sinfo.pm1a_evt_blk);
+               if (ACPI_FAILURE(status)) {
+                       goto exit;
+               }
+
+               /* PM1B is optional */
+
+               status =
+                   acpi_hw_low_level_read(16, &value2,
+                                          &acpi_sinfo.pm1b_evt_blk);
+               value1 |= value2;
+               break;
+
+
+       case ACPI_REGISTER_PM1_CONTROL: /* 16-bit access */
+
+               status =
+                   acpi_hw_low_level_read(16, &value1,
+                                          &acpi_sinfo.pm1a_cnt_blk);
+               if (ACPI_FAILURE(status)) {
+                       goto exit;
+               }
+
+               status =
+                   acpi_hw_low_level_read(16, &value2,
+                                          &acpi_sinfo.pm1b_cnt_blk);
+               value1 |= value2;
+               break;
+
+
+       default:
+               status = AE_BAD_PARAMETER;
+               break;
+       }
+
+      exit:
+
+       if (ACPI_SUCCESS(status)) {
+               *return_value = value1;
+       }
+
+       return_ACPI_STATUS(status);
+}
+
+/******************************************************************************
+ *
+ * FUNCTION:    acpi_hw_register_write
+ *
+ * PARAMETERS:  register_id         - ACPI Register ID 
+ *              Value               - The value to write
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Write to the specified ACPI register
+ *
+ * NOTE: In accordance with the ACPI specification, this function automatically
+ * preserves the value of the following bits, meaning that these bits cannot be
+ * changed via this interface:
+ *
+ * PM1_CONTROL[0] = SCI_EN
+ * PM1_CONTROL[9]
+ * PM1_STATUS[11]
+ *
+ * ACPI References:
+ * 1) Hardware Ignored Bits: When software writes to a register with ignored
+ *      bit fields, it preserves the ignored bit fields
+ * 2) SCI_EN: OSPM always preserves this bit position
+ *
+ 
******************************************************************************/
+
+acpi_status acpi_hw_register_write(u32 register_id, u32 value)
+{
+       acpi_status status;
+       u32 read_value;
+
+       ACPI_FUNCTION_TRACE(hw_register_write);
+
+       switch (register_id) {   //By now we just need handle PM1 status/PM1 
control
+       case ACPI_REGISTER_PM1_STATUS:  /* 16-bit access */
+
+               /* Perform a read first to preserve certain bits (per ACPI 
spec) */
+
+               status = acpi_hw_register_read(ACPI_REGISTER_PM1_STATUS,
+                                              &read_value);
+               if (ACPI_FAILURE(status)) {
+                       goto exit;
+               }
+
+               /* Insert the bits to be preserved */
+
+               ACPI_INSERT_BITS(value, ACPI_PM1_STATUS_PRESERVED_BITS,
+                                read_value);
+
+               /* Now we can write the data */
+
+               status =
+                   acpi_hw_low_level_write(16, value,
+                                           &acpi_sinfo.pm1a_evt_blk);
+               if (ACPI_FAILURE(status)) {
+                       goto exit;
+               }
+
+               /* PM1B is optional */
+
+               status =
+                   acpi_hw_low_level_write(16, value,
+                                           &acpi_sinfo.pm1b_evt_blk);
+               break;
+
+
+       case ACPI_REGISTER_PM1_CONTROL: /* 16-bit access */
+
+               /*
+                * Perform a read first to preserve certain bits (per ACPI spec)
+                *
+                * Note: This includes SCI_EN, we never want to change this bit
+                */
+               status = acpi_hw_register_read(ACPI_REGISTER_PM1_CONTROL,
+                                              &read_value);
+               if (ACPI_FAILURE(status)) {
+                       goto exit;
+               }
+
+               /* Insert the bits to be preserved */
+
+               ACPI_INSERT_BITS(value, ACPI_PM1_CONTROL_PRESERVED_BITS,
+                                read_value);
+
+               /* Now we can write the data */
+
+               status =
+                   acpi_hw_low_level_write(16, value,
+                                           &acpi_sinfo.pm1a_cnt_blk);
+               if (ACPI_FAILURE(status)) {
+                       goto exit;
+               }
+
+               status =
+                   acpi_hw_low_level_write(16, value,
+                                           &acpi_sinfo.pm1b_cnt_blk);
+               break;
+
+       case ACPI_REGISTER_PM1A_CONTROL:        /* 16-bit access */
+
+               status =
+                   acpi_hw_low_level_write(16, value,
+                                           &acpi_sinfo.pm1a_cnt_blk);
+               break;
+
+       case ACPI_REGISTER_PM1B_CONTROL:        /* 16-bit access */
+
+               status =
+                   acpi_hw_low_level_write(16, value,
+                                           &acpi_sinfo.pm1b_cnt_blk);
+               break;
+
+
+       default:
+               status = AE_BAD_PARAMETER;
+               break;
+       }
+
+      exit:
+
+       return_ACPI_STATUS(status);
+}
+
+/******************************************************************************
+ *
+ * FUNCTION:    acpi_hw_low_level_read
+ *
+ * PARAMETERS:  Width               - 8, 16, or 32
+ *              Value               - Where the value is returned
+ *              Reg                 - GAS register structure
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Read from either memory or IO space.
+ *
+ 
******************************************************************************/
+
+acpi_status
+acpi_hw_low_level_read(u32 width, u32 * value, struct acpi_generic_address 
*reg)
+{
+       u64 address;
+       acpi_status status;
+
+       ACPI_FUNCTION_NAME(hw_low_level_read);
+
+       /*
+        * Must have a valid pointer to a GAS structure, and
+        * 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) {
+               return (AE_OK);
+       }
+
+       /* Get a local copy of the address. Handles possible alignment issues */
+
+       ACPI_MOVE_64_TO_64(&address, &reg->address);
+       if (!address) {
+               return (AE_OK);
+       }
+       *value = 0;
+
+       /*
+        * Two address spaces supported: Memory or IO.
+        * PCI_Config is not supported here because the GAS struct is 
insufficient
+        */
+       switch (reg->space_id) {
+       case ACPI_ADR_SPACE_SYSTEM_MEMORY:
+
+               status = acpi_os_read_memory((acpi_physical_address) address,
+                                            value, width);
+               break;
+
+       case ACPI_ADR_SPACE_SYSTEM_IO:
+
+               status = acpi_os_read_port((acpi_io_address) address,
+                                          value, width);
+               break;
+
+       default:
+
+               return (AE_BAD_PARAMETER);
+       }
+
+       ACPI_DEBUG_PRINT((ACPI_DB_IO,
+                         "Read:  %8.8X width %2d from %8.8X%8.8X (%s)\n",
+                         *value, width,
+                         ACPI_FORMAT_UINT64(address),
+                         acpi_ut_get_region_name(reg->address_space_id)));
+
+       return (status);
+}
+
+/******************************************************************************
+ *
+ * FUNCTION:    acpi_hw_low_level_write
+ *
+ * PARAMETERS:  Width               - 8, 16, or 32
+ *              Value               - To be written
+ *              Reg                 - GAS register structure
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Write to either memory or IO space.
+ *
+ 
******************************************************************************/
+
+acpi_status
+acpi_hw_low_level_write(u32 width, u32 value, struct acpi_generic_address * 
reg)
+{
+       u64 address;
+       acpi_status status;
+
+       ACPI_FUNCTION_NAME(hw_low_level_write);
+
+       /*
+        * Must have a valid pointer to a GAS structure, and
+        * 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) {
+               return (AE_OK);
+       }
+
+       /* Get a local copy of the address. Handles possible alignment issues */
+
+       ACPI_MOVE_64_TO_64(&address, &reg->address);
+       if (!address) {
+               return (AE_OK);
+       }
+
+       /*
+        * Two address spaces supported: Memory or IO.
+        * PCI_Config is not supported here because the GAS struct is 
insufficient
+        */
+       switch (reg->space_id) {
+       case ACPI_ADR_SPACE_SYSTEM_MEMORY:
+
+               status = acpi_os_write_memory((acpi_physical_address) address,
+                                             value, width);
+               break;
+
+       case ACPI_ADR_SPACE_SYSTEM_IO:
+
+               status = acpi_os_write_port((acpi_io_address) address,
+                                           value, width);
+               break;
+
+       default:
+               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_FORMAT_UINT64(address),
+                         acpi_ut_get_region_name(reg->address_space_id)));
+
+       return (status);
+}
diff -r 70f9a2110421 -r 26a7a2d154e1 xen/drivers/acpi/osl.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/drivers/acpi/osl.c    Wed Mar 19 10:33:13 2008 +0000
@@ -0,0 +1,183 @@
+/*
+ *  acpi_osl.c - OS-dependent functions ($Revision: 83 $)
+ *
+ *  Copyright (C) 2000       Andrew Henroid
+ *  Copyright (C) 2001, 2002 Andy Grover <andrew.grover@xxxxxxxxx>
+ *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@xxxxxxxxx>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  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
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ */
+#include <asm/io.h>
+#include <xen/config.h>
+#include <xen/init.h>
+#include <xen/types.h>
+#include <xen/errno.h>
+#include <xen/acpi.h>
+#include <xen/numa.h>
+#include <acpi/acpi_bus.h>
+#include <acpi/acmacros.h>
+#include <acpi/acpiosxf.h>
+#include <acpi/platform/aclinux.h>
+#include <xen/spinlock.h>
+#include <xen/domain_page.h>
+
+#define _COMPONENT             ACPI_OS_SERVICES
+ACPI_MODULE_NAME("osl")
+#define PREFIX         "ACPI: "
+struct acpi_os_dpc {
+       acpi_osd_exec_callback function;
+       void *context;
+};
+
+#ifdef CONFIG_ACPI_CUSTOM_DSDT
+#include CONFIG_ACPI_CUSTOM_DSDT_FILE
+#endif
+
+#ifdef ENABLE_DEBUGGER
+#include <linux/kdb.h>
+
+/* stuff for debugger support */
+int acpi_in_debugger;
+EXPORT_SYMBOL(acpi_in_debugger);
+
+extern char line_buf[80];
+#endif                         /*ENABLE_DEBUGGER */
+
+int acpi_specific_hotkey_enabled = TRUE;
+EXPORT_SYMBOL(acpi_specific_hotkey_enabled);
+
+
+acpi_status acpi_os_read_port(acpi_io_address port, u32 * value, u32 width)
+{
+       u32 dummy;
+
+       if (!value)
+               value = &dummy;
+
+       *value = 0;
+       if (width <= 8) {
+               *(u8 *) value = inb(port);
+       } else if (width <= 16) {
+               *(u16 *) value = inw(port);
+       } else if (width <= 32) {
+               *(u32 *) value = inl(port);
+       } else {
+               BUG();
+       }
+
+       return AE_OK;
+}
+
+EXPORT_SYMBOL(acpi_os_read_port);
+
+acpi_status acpi_os_write_port(acpi_io_address port, u32 value, u32 width)
+{
+       if (width <= 8) {
+               outb(value, port);
+       } else if (width <= 16) {
+               outw(value, port);
+       } else if (width <= 32) {
+               outl(value, port);
+       } else {
+               BUG();
+       }
+
+       return AE_OK;
+}
+
+EXPORT_SYMBOL(acpi_os_write_port);
+
+acpi_status
+acpi_os_read_memory(acpi_physical_address phys_addr, u32 * value, u32 width)
+{
+       u32 dummy;
+       void __iomem *virt_addr;
+
+       virt_addr = map_domain_page(phys_addr>>PAGE_SHIFT);
+       if (!value)
+               value = &dummy;
+
+       switch (width) {
+       case 8:
+               *(u8 *) value = readb(virt_addr);
+               break;
+       case 16:
+               *(u16 *) value = readw(virt_addr);
+               break;
+       case 32:
+               *(u32 *) value = readl(virt_addr);
+               break;
+       default:
+               BUG();
+       }
+
+       unmap_domain_page(virt_addr);
+
+       return AE_OK;
+}
+
+acpi_status
+acpi_os_write_memory(acpi_physical_address phys_addr, u32 value, u32 width)
+{
+       void __iomem *virt_addr;
+
+       virt_addr = map_domain_page(phys_addr>>PAGE_SHIFT);
+
+       switch (width) {
+       case 8:
+               writeb(value, virt_addr);
+               break;
+       case 16:
+               writew(value, virt_addr);
+               break;
+       case 32:
+               writel(value, virt_addr);
+               break;
+       default:
+               BUG();
+       }
+
+       unmap_domain_page(virt_addr);
+
+       return AE_OK;
+}
+
+/*
+ * Acquire a spinlock.
+ *
+ * handle is a pointer to the spinlock_t.
+ */
+
+acpi_cpu_flags acpi_os_acquire_lock(acpi_spinlock lockp)
+{
+       acpi_cpu_flags flags;
+       spin_lock_irqsave(lockp, flags);
+       return flags;
+}
+
+/*
+ * Release a spinlock. See above.
+ */
+
+void acpi_os_release_lock(acpi_spinlock lockp, acpi_cpu_flags flags)
+{
+       spin_unlock_irqrestore(lockp, flags);
+}
+
diff -r 70f9a2110421 -r 26a7a2d154e1 xen/include/asm-x86/acpi.h
--- a/xen/include/asm-x86/acpi.h        Wed Mar 19 10:22:49 2008 +0000
+++ b/xen/include/asm-x86/acpi.h        Wed Mar 19 10:33:13 2008 +0000
@@ -26,6 +26,8 @@
 
 #include <xen/config.h>
 #include <acpi/pdc_intel.h>
+#include <acpi/acconfig.h>
+#include <acpi/actbl.h>
 
 #define COMPILER_DEPENDENT_INT64   long long
 #define COMPILER_DEPENDENT_UINT64  unsigned long long
@@ -146,10 +148,10 @@ extern int acpi_enter_state(u32 state);
 extern int acpi_enter_state(u32 state);
 
 struct acpi_sleep_info {
-    uint16_t pm1a_cnt;
-    uint16_t pm1b_cnt;
-    uint16_t pm1a_evt;
-    uint16_t pm1b_evt;
+    struct acpi_generic_address pm1a_cnt_blk;
+    struct acpi_generic_address pm1b_cnt_blk;
+    struct acpi_generic_address pm1a_evt_blk;
+    struct acpi_generic_address pm1b_evt_blk;
     uint16_t pm1a_cnt_val;
     uint16_t pm1b_cnt_val;
     uint32_t sleep_state;

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] x86 ACPI sleep: Fix a bug when ACPI registers in System_Memory, Xen patchbot-unstable <=