hwregs.c revision 167802
167754Smsmith 267754Smsmith/******************************************************************************* 367754Smsmith * 467754Smsmith * Module Name: hwregs - Read/write access functions for the various ACPI 567754Smsmith * control and status registers. 6167802Sjkim * $Revision: 1.187 $ 767754Smsmith * 867754Smsmith ******************************************************************************/ 967754Smsmith 1067754Smsmith/****************************************************************************** 1167754Smsmith * 1267754Smsmith * 1. Copyright Notice 1367754Smsmith * 14167802Sjkim * Some or all of this work - Copyright (c) 1999 - 2007, Intel Corp. 1570243Smsmith * All rights reserved. 1667754Smsmith * 1767754Smsmith * 2. License 1867754Smsmith * 1967754Smsmith * 2.1. This is your license from Intel Corp. under its intellectual property 2067754Smsmith * rights. You may have additional license terms from the party that provided 2167754Smsmith * you this software, covering your right to use that party's intellectual 2267754Smsmith * property rights. 2367754Smsmith * 2467754Smsmith * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a 2567754Smsmith * copy of the source code appearing in this file ("Covered Code") an 2667754Smsmith * irrevocable, perpetual, worldwide license under Intel's copyrights in the 2767754Smsmith * base code distributed originally by Intel ("Original Intel Code") to copy, 2867754Smsmith * make derivatives, distribute, use and display any portion of the Covered 2967754Smsmith * Code in any form, with the right to sublicense such rights; and 3067754Smsmith * 3167754Smsmith * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent 3267754Smsmith * license (with the right to sublicense), under only those claims of Intel 3367754Smsmith * patents that are infringed by the Original Intel Code, to make, use, sell, 3467754Smsmith * offer to sell, and import the Covered Code and derivative works thereof 3567754Smsmith * solely to the minimum extent necessary to exercise the above copyright 3667754Smsmith * license, and in no event shall the patent license extend to any additions 3767754Smsmith * to or modifications of the Original Intel Code. No other license or right 3867754Smsmith * is granted directly or by implication, estoppel or otherwise; 3967754Smsmith * 4067754Smsmith * The above copyright and patent license is granted only if the following 4167754Smsmith * conditions are met: 4267754Smsmith * 4367754Smsmith * 3. Conditions 4467754Smsmith * 4567754Smsmith * 3.1. Redistribution of Source with Rights to Further Distribute Source. 4667754Smsmith * Redistribution of source code of any substantial portion of the Covered 4767754Smsmith * Code or modification with rights to further distribute source must include 4867754Smsmith * the above Copyright Notice, the above License, this list of Conditions, 4967754Smsmith * and the following Disclaimer and Export Compliance provision. In addition, 5067754Smsmith * Licensee must cause all Covered Code to which Licensee contributes to 5167754Smsmith * contain a file documenting the changes Licensee made to create that Covered 5267754Smsmith * Code and the date of any change. Licensee must include in that file the 5367754Smsmith * documentation of any changes made by any predecessor Licensee. Licensee 5467754Smsmith * must include a prominent statement that the modification is derived, 5567754Smsmith * directly or indirectly, from Original Intel Code. 5667754Smsmith * 5767754Smsmith * 3.2. Redistribution of Source with no Rights to Further Distribute Source. 5867754Smsmith * Redistribution of source code of any substantial portion of the Covered 5967754Smsmith * Code or modification without rights to further distribute source must 6067754Smsmith * include the following Disclaimer and Export Compliance provision in the 6167754Smsmith * documentation and/or other materials provided with distribution. In 6267754Smsmith * addition, Licensee may not authorize further sublicense of source of any 6367754Smsmith * portion of the Covered Code, and must include terms to the effect that the 6467754Smsmith * license from Licensee to its licensee is limited to the intellectual 6567754Smsmith * property embodied in the software Licensee provides to its licensee, and 6667754Smsmith * not to intellectual property embodied in modifications its licensee may 6767754Smsmith * make. 6867754Smsmith * 6967754Smsmith * 3.3. Redistribution of Executable. Redistribution in executable form of any 7067754Smsmith * substantial portion of the Covered Code or modification must reproduce the 7167754Smsmith * above Copyright Notice, and the following Disclaimer and Export Compliance 7267754Smsmith * provision in the documentation and/or other materials provided with the 7367754Smsmith * distribution. 7467754Smsmith * 7567754Smsmith * 3.4. Intel retains all right, title, and interest in and to the Original 7667754Smsmith * Intel Code. 7767754Smsmith * 7867754Smsmith * 3.5. Neither the name Intel nor any other trademark owned or controlled by 7967754Smsmith * Intel shall be used in advertising or otherwise to promote the sale, use or 8067754Smsmith * other dealings in products derived from or relating to the Covered Code 8167754Smsmith * without prior written authorization from Intel. 8267754Smsmith * 8367754Smsmith * 4. Disclaimer and Export Compliance 8467754Smsmith * 8567754Smsmith * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED 8667754Smsmith * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE 8767754Smsmith * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, 8867754Smsmith * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY 8967754Smsmith * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY 9067754Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A 9167754Smsmith * PARTICULAR PURPOSE. 9267754Smsmith * 9367754Smsmith * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES 9467754Smsmith * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR 9567754Smsmith * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, 9667754Smsmith * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY 9767754Smsmith * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL 9867754Smsmith * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS 9967754Smsmith * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY 10067754Smsmith * LIMITED REMEDY. 10167754Smsmith * 10267754Smsmith * 4.3. Licensee shall not export, either directly or indirectly, any of this 10367754Smsmith * software or system incorporating such software without first obtaining any 10467754Smsmith * required license or other approval from the U. S. Department of Commerce or 10567754Smsmith * any other agency or department of the United States Government. In the 10667754Smsmith * event Licensee exports any such software from the United States or 10767754Smsmith * re-exports any such software from a foreign destination, Licensee shall 10867754Smsmith * ensure that the distribution and export/re-export of the software is in 10967754Smsmith * compliance with all laws, regulations, orders, or other restrictions of the 11067754Smsmith * U.S. Export Administration Regulations. Licensee agrees that neither it nor 11167754Smsmith * any of its subsidiaries will export/re-export any technical data, process, 11267754Smsmith * software, or service, directly or indirectly, to any country for which the 11367754Smsmith * United States government or any agency thereof requires an export license, 11467754Smsmith * other governmental approval, or letter of assurance, without first obtaining 11567754Smsmith * such license, approval or letter. 11667754Smsmith * 11767754Smsmith *****************************************************************************/ 11867754Smsmith 11967754Smsmith#define __HWREGS_C__ 12067754Smsmith 121151600Sobrien#include <contrib/dev/acpica/acpi.h> 122151600Sobrien#include <contrib/dev/acpica/acnamesp.h> 123151600Sobrien#include <contrib/dev/acpica/acevents.h> 12467754Smsmith 12577424Smsmith#define _COMPONENT ACPI_HARDWARE 12691116Smsmith ACPI_MODULE_NAME ("hwregs") 12767754Smsmith 12867754Smsmith 12967754Smsmith/******************************************************************************* 13067754Smsmith * 13167754Smsmith * FUNCTION: AcpiHwClearAcpiStatus 13267754Smsmith * 133167802Sjkim * PARAMETERS: None 13467754Smsmith * 135167802Sjkim * RETURN: None 13667754Smsmith * 13767754Smsmith * DESCRIPTION: Clears all fixed and general purpose status bits 138138287Smarks * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED 13967754Smsmith * 14067754Smsmith ******************************************************************************/ 14167754Smsmith 14299679SiwasakiACPI_STATUS 143117521SnjlAcpiHwClearAcpiStatus ( 144167802Sjkim void) 14567754Smsmith{ 14691116Smsmith ACPI_STATUS Status; 147167802Sjkim ACPI_CPU_FLAGS LockFlags = 0; 14867754Smsmith 14967754Smsmith 150167802Sjkim ACPI_FUNCTION_TRACE (HwClearAcpiStatus); 15167754Smsmith 15267754Smsmith 15382367Smsmith ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %04X to %04X\n", 15491116Smsmith ACPI_BITMASK_ALL_FIXED_STATUS, 155167802Sjkim (UINT16) AcpiGbl_FADT.XPm1aEventBlock.Address)); 15667754Smsmith 157167802Sjkim LockFlags = AcpiOsAcquireLock (AcpiGbl_HardwareLock); 15867754Smsmith 159151937Sjkim Status = AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK, 160151937Sjkim ACPI_REGISTER_PM1_STATUS, 161151937Sjkim ACPI_BITMASK_ALL_FIXED_STATUS); 16299679Siwasaki if (ACPI_FAILURE (Status)) 16399679Siwasaki { 16499679Siwasaki goto UnlockAndExit; 16599679Siwasaki } 16667754Smsmith 16791116Smsmith /* Clear the fixed events */ 16869450Smsmith 169167802Sjkim if (AcpiGbl_FADT.XPm1bEventBlock.Address) 17067754Smsmith { 17199679Siwasaki Status = AcpiHwLowLevelWrite (16, ACPI_BITMASK_ALL_FIXED_STATUS, 172167802Sjkim &AcpiGbl_FADT.XPm1bEventBlock); 17399679Siwasaki if (ACPI_FAILURE (Status)) 17499679Siwasaki { 17599679Siwasaki goto UnlockAndExit; 17699679Siwasaki } 17767754Smsmith } 17867754Smsmith 179114237Snjl /* Clear the GPE Bits in all GPE registers in all GPE blocks */ 18067754Smsmith 181151937Sjkim Status = AcpiEvWalkGpeList (AcpiHwClearGpeBlock); 182117521Snjl 183117521SnjlUnlockAndExit: 184167802Sjkim AcpiOsReleaseLock (AcpiGbl_HardwareLock, LockFlags); 18599679Siwasaki return_ACPI_STATUS (Status); 18667754Smsmith} 18767754Smsmith 18867754Smsmith 18967754Smsmith/******************************************************************************* 19067754Smsmith * 19199679Siwasaki * FUNCTION: AcpiGetSleepTypeData 19267754Smsmith * 19391116Smsmith * PARAMETERS: SleepState - Numeric sleep state 19491116Smsmith * *SleepTypeA - Where SLP_TYPa is returned 19591116Smsmith * *SleepTypeB - Where SLP_TYPb is returned 19667754Smsmith * 19767754Smsmith * RETURN: Status - ACPI status 19867754Smsmith * 19991116Smsmith * DESCRIPTION: Obtain the SLP_TYPa and SLP_TYPb values for the requested sleep 20091116Smsmith * state. 20167754Smsmith * 20267754Smsmith ******************************************************************************/ 20367754Smsmith 20467754SmsmithACPI_STATUS 20599679SiwasakiAcpiGetSleepTypeData ( 20667754Smsmith UINT8 SleepState, 20791116Smsmith UINT8 *SleepTypeA, 20891116Smsmith UINT8 *SleepTypeB) 20967754Smsmith{ 21067754Smsmith ACPI_STATUS Status = AE_OK; 211167802Sjkim ACPI_EVALUATE_INFO *Info; 21267754Smsmith 21367754Smsmith 214167802Sjkim ACPI_FUNCTION_TRACE (AcpiGetSleepTypeData); 21567754Smsmith 21667754Smsmith 217151937Sjkim /* Validate parameters */ 218151937Sjkim 21967754Smsmith if ((SleepState > ACPI_S_STATES_MAX) || 22091116Smsmith !SleepTypeA || !SleepTypeB) 22167754Smsmith { 22267754Smsmith return_ACPI_STATUS (AE_BAD_PARAMETER); 22367754Smsmith } 22467754Smsmith 225167802Sjkim /* Allocate the evaluation information block */ 226167802Sjkim 227167802Sjkim Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO)); 228167802Sjkim if (!Info) 229167802Sjkim { 230167802Sjkim return_ACPI_STATUS (AE_NO_MEMORY); 231167802Sjkim } 232167802Sjkim 233167802Sjkim Info->Pathname = ACPI_CAST_PTR (char, AcpiGbl_SleepStateNames[SleepState]); 234167802Sjkim 235151937Sjkim /* Evaluate the namespace object containing the values for this state */ 236151937Sjkim 237167802Sjkim Status = AcpiNsEvaluate (Info); 23867754Smsmith if (ACPI_FAILURE (Status)) 23967754Smsmith { 240151937Sjkim ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, 241151937Sjkim "%s while evaluating SleepState [%s]\n", 242167802Sjkim AcpiFormatException (Status), Info->Pathname)); 243114237Snjl 244167802Sjkim goto Cleanup; 24567754Smsmith } 24667754Smsmith 24799679Siwasaki /* Must have a return object */ 24899679Siwasaki 249167802Sjkim if (!Info->ReturnObject) 25067754Smsmith { 251167802Sjkim ACPI_ERROR ((AE_INFO, "No Sleep State object returned from [%s]", 252167802Sjkim Info->Pathname)); 25399679Siwasaki Status = AE_NOT_EXIST; 25467754Smsmith } 25567754Smsmith 25699679Siwasaki /* It must be of type Package */ 25767754Smsmith 258167802Sjkim else if (ACPI_GET_OBJECT_TYPE (Info->ReturnObject) != ACPI_TYPE_PACKAGE) 25999679Siwasaki { 260167802Sjkim ACPI_ERROR ((AE_INFO, "Sleep State return object is not a Package")); 26199679Siwasaki Status = AE_AML_OPERAND_TYPE; 26299679Siwasaki } 26367754Smsmith 264151937Sjkim /* 265167802Sjkim * The package must have at least two elements. NOTE (March 2005): This 266151937Sjkim * goes against the current ACPI spec which defines this object as a 267167802Sjkim * package with one encoded DWORD element. However, existing practice 268151937Sjkim * by BIOS vendors seems to be to have 2 or more elements, at least 269151937Sjkim * one per sleep type (A/B). 270151937Sjkim */ 271167802Sjkim else if (Info->ReturnObject->Package.Count < 2) 27267754Smsmith { 273167802Sjkim ACPI_ERROR ((AE_INFO, 274167802Sjkim "Sleep State return package does not have at least two elements")); 27591116Smsmith Status = AE_AML_NO_OPERAND; 27667754Smsmith } 27799679Siwasaki 27899679Siwasaki /* The first two elements must both be of type Integer */ 27999679Siwasaki 280167802Sjkim else if ((ACPI_GET_OBJECT_TYPE (Info->ReturnObject->Package.Elements[0]) 281151937Sjkim != ACPI_TYPE_INTEGER) || 282167802Sjkim (ACPI_GET_OBJECT_TYPE (Info->ReturnObject->Package.Elements[1]) 283151937Sjkim != ACPI_TYPE_INTEGER)) 28467754Smsmith { 285167802Sjkim ACPI_ERROR ((AE_INFO, 286167802Sjkim "Sleep State return package elements are not both Integers (%s, %s)", 287167802Sjkim AcpiUtGetObjectTypeName (Info->ReturnObject->Package.Elements[0]), 288167802Sjkim AcpiUtGetObjectTypeName (Info->ReturnObject->Package.Elements[1]))); 28991116Smsmith Status = AE_AML_OPERAND_TYPE; 29067754Smsmith } 29167754Smsmith else 29267754Smsmith { 293151937Sjkim /* Valid _Sx_ package size, type, and value */ 294151937Sjkim 295151937Sjkim *SleepTypeA = (UINT8) 296167802Sjkim (Info->ReturnObject->Package.Elements[0])->Integer.Value; 297151937Sjkim *SleepTypeB = (UINT8) 298167802Sjkim (Info->ReturnObject->Package.Elements[1])->Integer.Value; 29967754Smsmith } 30067754Smsmith 30167754Smsmith if (ACPI_FAILURE (Status)) 30267754Smsmith { 303167802Sjkim ACPI_EXCEPTION ((AE_INFO, Status, 304167802Sjkim "While evaluating SleepState [%s], bad Sleep object %p type %s", 305167802Sjkim Info->Pathname, Info->ReturnObject, 306167802Sjkim AcpiUtGetObjectTypeName (Info->ReturnObject))); 30767754Smsmith } 30867754Smsmith 309167802Sjkim AcpiUtRemoveReference (Info->ReturnObject); 310167802Sjkim 311167802SjkimCleanup: 312167802Sjkim ACPI_FREE (Info); 31367754Smsmith return_ACPI_STATUS (Status); 31467754Smsmith} 31567754Smsmith 316167802SjkimACPI_EXPORT_SYMBOL (AcpiGetSleepTypeData) 31767754Smsmith 318167802Sjkim 31967754Smsmith/******************************************************************************* 32067754Smsmith * 32191116Smsmith * FUNCTION: AcpiHwGetRegisterBitMask 32267754Smsmith * 32399679Siwasaki * PARAMETERS: RegisterId - Index of ACPI Register to access 324102550Siwasaki * 325151937Sjkim * RETURN: The bitmask to be used when accessing the register 32691116Smsmith * 327151937Sjkim * DESCRIPTION: Map RegisterId into a register bitmask. 32891116Smsmith * 32991116Smsmith ******************************************************************************/ 33091116Smsmith 33191116SmsmithACPI_BIT_REGISTER_INFO * 33291116SmsmithAcpiHwGetBitRegisterInfo ( 33391116Smsmith UINT32 RegisterId) 33491116Smsmith{ 335167802Sjkim ACPI_FUNCTION_ENTRY (); 33691116Smsmith 33791116Smsmith 33891116Smsmith if (RegisterId > ACPI_BITREG_MAX) 33991116Smsmith { 340167802Sjkim ACPI_ERROR ((AE_INFO, "Invalid BitRegister ID: %X", RegisterId)); 34191116Smsmith return (NULL); 34291116Smsmith } 34391116Smsmith 34491116Smsmith return (&AcpiGbl_BitRegisterInfo[RegisterId]); 34591116Smsmith} 34691116Smsmith 34791116Smsmith 34891116Smsmith/******************************************************************************* 34991116Smsmith * 35099679Siwasaki * FUNCTION: AcpiGetRegister 35191116Smsmith * 352117521Snjl * PARAMETERS: RegisterId - ID of ACPI BitRegister to access 353117521Snjl * ReturnValue - Value that was read from the register 35467754Smsmith * 355167802Sjkim * RETURN: Status and the value read from specified Register. Value 356138287Smarks * returned is normalized to bit0 (is shifted all the way right) 35767754Smsmith * 35891116Smsmith * DESCRIPTION: ACPI BitRegister read function. 35967754Smsmith * 36067754Smsmith ******************************************************************************/ 36167754Smsmith 36299679SiwasakiACPI_STATUS 36399679SiwasakiAcpiGetRegister ( 36467754Smsmith UINT32 RegisterId, 365167802Sjkim UINT32 *ReturnValue) 36667754Smsmith{ 36767754Smsmith UINT32 RegisterValue = 0; 36891116Smsmith ACPI_BIT_REGISTER_INFO *BitRegInfo; 36999679Siwasaki ACPI_STATUS Status; 37067754Smsmith 37177424Smsmith 372167802Sjkim ACPI_FUNCTION_TRACE (AcpiGetRegister); 37367754Smsmith 37467754Smsmith 37591116Smsmith /* Get the info structure corresponding to the requested ACPI Register */ 37691116Smsmith 37791116Smsmith BitRegInfo = AcpiHwGetBitRegisterInfo (RegisterId); 37891116Smsmith if (!BitRegInfo) 37977424Smsmith { 38091116Smsmith return_ACPI_STATUS (AE_BAD_PARAMETER); 38169450Smsmith } 38267754Smsmith 383138287Smarks /* Read from the register */ 384138287Smarks 385167802Sjkim Status = AcpiHwRegisterRead (ACPI_MTX_LOCK, 386167802Sjkim BitRegInfo->ParentRegister, &RegisterValue); 38799679Siwasaki 38899679Siwasaki if (ACPI_SUCCESS (Status)) 38999679Siwasaki { 39099679Siwasaki /* Normalize the value that was read */ 39167754Smsmith 392102550Siwasaki RegisterValue = ((RegisterValue & BitRegInfo->AccessBitMask) 39399679Siwasaki >> BitRegInfo->BitPosition); 39467754Smsmith 39599679Siwasaki *ReturnValue = RegisterValue; 39699679Siwasaki 397123315Snjl ACPI_DEBUG_PRINT ((ACPI_DB_IO, "Read value %8.8X register %X\n", 398167802Sjkim RegisterValue, BitRegInfo->ParentRegister)); 39999679Siwasaki } 40099679Siwasaki 40199679Siwasaki return_ACPI_STATUS (Status); 40291116Smsmith} 40367754Smsmith 404167802SjkimACPI_EXPORT_SYMBOL (AcpiGetRegister) 40567754Smsmith 406167802Sjkim 40791116Smsmith/******************************************************************************* 40891116Smsmith * 40999679Siwasaki * FUNCTION: AcpiSetRegister 41091116Smsmith * 41191116Smsmith * PARAMETERS: RegisterId - ID of ACPI BitRegister to access 41291116Smsmith * Value - (only used on write) value to write to the 413138287Smarks * Register, NOT pre-normalized to the bit pos 41491116Smsmith * 415138287Smarks * RETURN: Status 41691116Smsmith * 41791116Smsmith * DESCRIPTION: ACPI Bit Register write function. 41891116Smsmith * 41991116Smsmith ******************************************************************************/ 42067754Smsmith 42199679SiwasakiACPI_STATUS 42299679SiwasakiAcpiSetRegister ( 42391116Smsmith UINT32 RegisterId, 424167802Sjkim UINT32 Value) 42591116Smsmith{ 42691116Smsmith UINT32 RegisterValue = 0; 42791116Smsmith ACPI_BIT_REGISTER_INFO *BitRegInfo; 42899679Siwasaki ACPI_STATUS Status; 429167802Sjkim ACPI_CPU_FLAGS LockFlags; 43067754Smsmith 43167754Smsmith 432167802Sjkim ACPI_FUNCTION_TRACE_U32 (AcpiSetRegister, RegisterId); 43367754Smsmith 43467754Smsmith 43591116Smsmith /* Get the info structure corresponding to the requested ACPI Register */ 43667754Smsmith 43791116Smsmith BitRegInfo = AcpiHwGetBitRegisterInfo (RegisterId); 43891116Smsmith if (!BitRegInfo) 43991116Smsmith { 440167802Sjkim ACPI_ERROR ((AE_INFO, "Bad ACPI HW RegisterId: %X", RegisterId)); 44191116Smsmith return_ACPI_STATUS (AE_BAD_PARAMETER); 44291116Smsmith } 44367754Smsmith 444167802Sjkim LockFlags = AcpiOsAcquireLock (AcpiGbl_HardwareLock); 44599679Siwasaki 44691116Smsmith /* Always do a register read first so we can insert the new bits */ 44767754Smsmith 448102550Siwasaki Status = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK, 449151937Sjkim BitRegInfo->ParentRegister, &RegisterValue); 45099679Siwasaki if (ACPI_FAILURE (Status)) 45199679Siwasaki { 45299679Siwasaki goto UnlockAndExit; 45399679Siwasaki } 45467754Smsmith 45591116Smsmith /* 45691116Smsmith * Decode the Register ID 457123315Snjl * Register ID = [Register block ID] | [bit ID] 45891116Smsmith * 459123315Snjl * Check bit ID to fine locate Register offset. 46091116Smsmith * Check Mask to determine Register offset, and then read-write. 46191116Smsmith */ 46291116Smsmith switch (BitRegInfo->ParentRegister) 46391116Smsmith { 46491116Smsmith case ACPI_REGISTER_PM1_STATUS: 46567754Smsmith 46691116Smsmith /* 467167802Sjkim * Status Registers are different from the rest. Clear by 468167802Sjkim * writing 1, and writing 0 has no effect. So, the only relevant 46991116Smsmith * information is the single bit we're interested in, all others should 470123315Snjl * be written as 0 so they will be left unchanged. 47191116Smsmith */ 472102550Siwasaki Value = ACPI_REGISTER_PREPARE_BITS (Value, 47399679Siwasaki BitRegInfo->BitPosition, BitRegInfo->AccessBitMask); 47491116Smsmith if (Value) 47569450Smsmith { 476102550Siwasaki Status = AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK, 47799679Siwasaki ACPI_REGISTER_PM1_STATUS, (UINT16) Value); 47891116Smsmith RegisterValue = 0; 47969450Smsmith } 48067754Smsmith break; 48167754Smsmith 48267754Smsmith 48391116Smsmith case ACPI_REGISTER_PM1_ENABLE: 48467754Smsmith 485102550Siwasaki ACPI_REGISTER_INSERT_VALUE (RegisterValue, BitRegInfo->BitPosition, 486167802Sjkim BitRegInfo->AccessBitMask, Value); 48767754Smsmith 488102550Siwasaki Status = AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK, 489151937Sjkim ACPI_REGISTER_PM1_ENABLE, (UINT16) RegisterValue); 49091116Smsmith break; 49167754Smsmith 49267754Smsmith 49391116Smsmith case ACPI_REGISTER_PM1_CONTROL: 49467754Smsmith 49569450Smsmith /* 496123315Snjl * Write the PM1 Control register. 49769450Smsmith * Note that at this level, the fact that there are actually TWO 498123315Snjl * registers (A and B - and B may not exist) is abstracted. 49969450Smsmith */ 500167802Sjkim ACPI_DEBUG_PRINT ((ACPI_DB_IO, "PM1 control: Read %X\n", 501167802Sjkim RegisterValue)); 50269450Smsmith 503102550Siwasaki ACPI_REGISTER_INSERT_VALUE (RegisterValue, BitRegInfo->BitPosition, 504167802Sjkim BitRegInfo->AccessBitMask, Value); 50567754Smsmith 506117525Snjl Status = AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK, 507151937Sjkim ACPI_REGISTER_PM1_CONTROL, (UINT16) RegisterValue); 50867754Smsmith break; 50967754Smsmith 51067754Smsmith 51191116Smsmith case ACPI_REGISTER_PM2_CONTROL: 51267754Smsmith 513102550Siwasaki Status = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK, 51499679Siwasaki ACPI_REGISTER_PM2_CONTROL, &RegisterValue); 51599679Siwasaki if (ACPI_FAILURE (Status)) 51699679Siwasaki { 51799679Siwasaki goto UnlockAndExit; 51899679Siwasaki } 51967754Smsmith 52085756Smsmith ACPI_DEBUG_PRINT ((ACPI_DB_IO, "PM2 control: Read %X from %8.8X%8.8X\n", 521102550Siwasaki RegisterValue, 522167802Sjkim ACPI_FORMAT_UINT64 (AcpiGbl_FADT.XPm2ControlBlock.Address))); 52369450Smsmith 524102550Siwasaki ACPI_REGISTER_INSERT_VALUE (RegisterValue, BitRegInfo->BitPosition, 52599679Siwasaki BitRegInfo->AccessBitMask, Value); 52667754Smsmith 52799679Siwasaki ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %4.4X to %8.8X%8.8X\n", 52885756Smsmith RegisterValue, 529167802Sjkim ACPI_FORMAT_UINT64 (AcpiGbl_FADT.XPm2ControlBlock.Address))); 53067754Smsmith 53199679Siwasaki Status = AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK, 532151937Sjkim ACPI_REGISTER_PM2_CONTROL, (UINT8) (RegisterValue)); 53367754Smsmith break; 53467754Smsmith 53567754Smsmith 53667754Smsmith default: 53767754Smsmith break; 53867754Smsmith } 53967754Smsmith 54099679Siwasaki 54199679SiwasakiUnlockAndExit: 54299679Siwasaki 543167802Sjkim AcpiOsReleaseLock (AcpiGbl_HardwareLock, LockFlags); 54467754Smsmith 54591116Smsmith /* Normalize the value that was read */ 54669450Smsmith 547151937Sjkim ACPI_DEBUG_EXEC (RegisterValue = 548151937Sjkim ((RegisterValue & BitRegInfo->AccessBitMask) >> 549151937Sjkim BitRegInfo->BitPosition)); 55067754Smsmith 551117521Snjl ACPI_DEBUG_PRINT ((ACPI_DB_IO, "Set bits: %8.8X actual %8.8X register %X\n", 552167802Sjkim Value, RegisterValue, BitRegInfo->ParentRegister)); 55399679Siwasaki return_ACPI_STATUS (Status); 55467754Smsmith} 55569450Smsmith 556167802SjkimACPI_EXPORT_SYMBOL (AcpiSetRegister) 55769450Smsmith 558167802Sjkim 55969450Smsmith/****************************************************************************** 56069450Smsmith * 56169450Smsmith * FUNCTION: AcpiHwRegisterRead 56269450Smsmith * 563167802Sjkim * PARAMETERS: UseLock - Lock hardware? True/False 564167802Sjkim * RegisterId - ACPI Register ID 565151937Sjkim * ReturnValue - Where the register value is returned 56669450Smsmith * 567138287Smarks * RETURN: Status and the value read. 56869450Smsmith * 569167802Sjkim * DESCRIPTION: Read from the specified ACPI register 57069450Smsmith * 57169450Smsmith ******************************************************************************/ 57269450Smsmith 57399679SiwasakiACPI_STATUS 57469450SmsmithAcpiHwRegisterRead ( 57569450Smsmith BOOLEAN UseLock, 57699679Siwasaki UINT32 RegisterId, 57799679Siwasaki UINT32 *ReturnValue) 57869450Smsmith{ 57999679Siwasaki UINT32 Value1 = 0; 58099679Siwasaki UINT32 Value2 = 0; 58199679Siwasaki ACPI_STATUS Status; 582167802Sjkim ACPI_CPU_FLAGS LockFlags = 0; 58369450Smsmith 58477424Smsmith 585167802Sjkim ACPI_FUNCTION_TRACE (HwRegisterRead); 58669450Smsmith 58777424Smsmith 58869450Smsmith if (ACPI_MTX_LOCK == UseLock) 58969450Smsmith { 590167802Sjkim LockFlags = AcpiOsAcquireLock (AcpiGbl_HardwareLock); 59169450Smsmith } 59269450Smsmith 59391116Smsmith switch (RegisterId) 59469450Smsmith { 59591116Smsmith case ACPI_REGISTER_PM1_STATUS: /* 16-bit access */ 59669450Smsmith 597167802Sjkim Status = AcpiHwLowLevelRead (16, &Value1, &AcpiGbl_FADT.XPm1aEventBlock); 59899679Siwasaki if (ACPI_FAILURE (Status)) 59999679Siwasaki { 60099679Siwasaki goto UnlockAndExit; 60199679Siwasaki } 60299679Siwasaki 603117521Snjl /* PM1B is optional */ 604117521Snjl 605167802Sjkim Status = AcpiHwLowLevelRead (16, &Value2, &AcpiGbl_FADT.XPm1bEventBlock); 60699679Siwasaki Value1 |= Value2; 60769450Smsmith break; 60869450Smsmith 60969450Smsmith 610117521Snjl case ACPI_REGISTER_PM1_ENABLE: /* 16-bit access */ 61169450Smsmith 612117521Snjl Status = AcpiHwLowLevelRead (16, &Value1, &AcpiGbl_XPm1aEnable); 61399679Siwasaki if (ACPI_FAILURE (Status)) 61499679Siwasaki { 61599679Siwasaki goto UnlockAndExit; 61699679Siwasaki } 61799679Siwasaki 618117521Snjl /* PM1B is optional */ 619117521Snjl 620117521Snjl Status = AcpiHwLowLevelRead (16, &Value2, &AcpiGbl_XPm1bEnable); 62199679Siwasaki Value1 |= Value2; 62269450Smsmith break; 62369450Smsmith 62469450Smsmith 62591116Smsmith case ACPI_REGISTER_PM1_CONTROL: /* 16-bit access */ 62669450Smsmith 627167802Sjkim Status = AcpiHwLowLevelRead (16, &Value1, &AcpiGbl_FADT.XPm1aControlBlock); 62899679Siwasaki if (ACPI_FAILURE (Status)) 62999679Siwasaki { 63099679Siwasaki goto UnlockAndExit; 63199679Siwasaki } 63299679Siwasaki 633167802Sjkim Status = AcpiHwLowLevelRead (16, &Value2, &AcpiGbl_FADT.XPm1bControlBlock); 63499679Siwasaki Value1 |= Value2; 63569450Smsmith break; 63669450Smsmith 63769450Smsmith 63891116Smsmith case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */ 63969450Smsmith 640167802Sjkim Status = AcpiHwLowLevelRead (8, &Value1, &AcpiGbl_FADT.XPm2ControlBlock); 64169450Smsmith break; 64269450Smsmith 64369450Smsmith 64491116Smsmith case ACPI_REGISTER_PM_TIMER: /* 32-bit access */ 64569450Smsmith 646167802Sjkim Status = AcpiHwLowLevelRead (32, &Value1, &AcpiGbl_FADT.XPmTimerBlock); 64769450Smsmith break; 64869450Smsmith 64991116Smsmith case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */ 65069450Smsmith 651167802Sjkim Status = AcpiOsReadPort (AcpiGbl_FADT.SmiCommand, &Value1, 8); 65269450Smsmith break; 65369450Smsmith 65469450Smsmith default: 655167802Sjkim ACPI_ERROR ((AE_INFO, "Unknown Register ID: %X", 656151937Sjkim RegisterId)); 65799679Siwasaki Status = AE_BAD_PARAMETER; 65869450Smsmith break; 65969450Smsmith } 66069450Smsmith 66199679SiwasakiUnlockAndExit: 66269450Smsmith if (ACPI_MTX_LOCK == UseLock) 66369450Smsmith { 664167802Sjkim AcpiOsReleaseLock (AcpiGbl_HardwareLock, LockFlags); 66569450Smsmith } 66669450Smsmith 66799679Siwasaki if (ACPI_SUCCESS (Status)) 66899679Siwasaki { 66999679Siwasaki *ReturnValue = Value1; 67099679Siwasaki } 67199679Siwasaki 67299679Siwasaki return_ACPI_STATUS (Status); 67369450Smsmith} 67469450Smsmith 67569450Smsmith 67669450Smsmith/****************************************************************************** 67769450Smsmith * 67869450Smsmith * FUNCTION: AcpiHwRegisterWrite 67969450Smsmith * 680167802Sjkim * PARAMETERS: UseLock - Lock hardware? True/False 681167802Sjkim * RegisterId - ACPI Register ID 682138287Smarks * Value - The value to write 68369450Smsmith * 684138287Smarks * RETURN: Status 68569450Smsmith * 686167802Sjkim * DESCRIPTION: Write to the specified ACPI register 68769450Smsmith * 688167802Sjkim * NOTE: In accordance with the ACPI specification, this function automatically 689167802Sjkim * preserves the value of the following bits, meaning that these bits cannot be 690167802Sjkim * changed via this interface: 691167802Sjkim * 692167802Sjkim * PM1_CONTROL[0] = SCI_EN 693167802Sjkim * PM1_CONTROL[9] 694167802Sjkim * PM1_STATUS[11] 695167802Sjkim * 696167802Sjkim * ACPI References: 697167802Sjkim * 1) Hardware Ignored Bits: When software writes to a register with ignored 698167802Sjkim * bit fields, it preserves the ignored bit fields 699167802Sjkim * 2) SCI_EN: OSPM always preserves this bit position 700167802Sjkim * 70169450Smsmith ******************************************************************************/ 70269450Smsmith 70399679SiwasakiACPI_STATUS 70469450SmsmithAcpiHwRegisterWrite ( 70569450Smsmith BOOLEAN UseLock, 70669450Smsmith UINT32 RegisterId, 70769450Smsmith UINT32 Value) 70869450Smsmith{ 70999679Siwasaki ACPI_STATUS Status; 710167802Sjkim ACPI_CPU_FLAGS LockFlags = 0; 711167802Sjkim UINT32 ReadValue; 71269450Smsmith 71369450Smsmith 714167802Sjkim ACPI_FUNCTION_TRACE (HwRegisterWrite); 71569450Smsmith 71683174Smsmith 71769450Smsmith if (ACPI_MTX_LOCK == UseLock) 71869450Smsmith { 719167802Sjkim LockFlags = AcpiOsAcquireLock (AcpiGbl_HardwareLock); 72069450Smsmith } 72169450Smsmith 72291116Smsmith switch (RegisterId) 72369450Smsmith { 72491116Smsmith case ACPI_REGISTER_PM1_STATUS: /* 16-bit access */ 72569450Smsmith 726167802Sjkim /* Perform a read first to preserve certain bits (per ACPI spec) */ 727167802Sjkim 728167802Sjkim Status = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK, 729167802Sjkim ACPI_REGISTER_PM1_STATUS, &ReadValue); 73099679Siwasaki if (ACPI_FAILURE (Status)) 73199679Siwasaki { 73299679Siwasaki goto UnlockAndExit; 73399679Siwasaki } 73499679Siwasaki 735167802Sjkim /* Insert the bits to be preserved */ 736167802Sjkim 737167802Sjkim ACPI_INSERT_BITS (Value, ACPI_PM1_STATUS_PRESERVED_BITS, ReadValue); 738167802Sjkim 739167802Sjkim /* Now we can write the data */ 740167802Sjkim 741167802Sjkim Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT.XPm1aEventBlock); 742167802Sjkim if (ACPI_FAILURE (Status)) 743167802Sjkim { 744167802Sjkim goto UnlockAndExit; 745167802Sjkim } 746167802Sjkim 747117521Snjl /* PM1B is optional */ 748117521Snjl 749167802Sjkim Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT.XPm1bEventBlock); 75069450Smsmith break; 75169450Smsmith 75269450Smsmith 753167802Sjkim case ACPI_REGISTER_PM1_ENABLE: /* 16-bit access */ 75469450Smsmith 755117521Snjl Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_XPm1aEnable); 75699679Siwasaki if (ACPI_FAILURE (Status)) 75799679Siwasaki { 75899679Siwasaki goto UnlockAndExit; 75999679Siwasaki } 76099679Siwasaki 761117521Snjl /* PM1B is optional */ 762117521Snjl 763117521Snjl Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_XPm1bEnable); 76469450Smsmith break; 76569450Smsmith 76669450Smsmith 76791116Smsmith case ACPI_REGISTER_PM1_CONTROL: /* 16-bit access */ 76869450Smsmith 769167802Sjkim /* 770167802Sjkim * Perform a read first to preserve certain bits (per ACPI spec) 771167802Sjkim * 772167802Sjkim * Note: This includes SCI_EN, we never want to change this bit 773167802Sjkim */ 774167802Sjkim Status = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK, 775167802Sjkim ACPI_REGISTER_PM1_CONTROL, &ReadValue); 77699679Siwasaki if (ACPI_FAILURE (Status)) 77799679Siwasaki { 77899679Siwasaki goto UnlockAndExit; 77999679Siwasaki } 78099679Siwasaki 781167802Sjkim /* Insert the bits to be preserved */ 782167802Sjkim 783167802Sjkim ACPI_INSERT_BITS (Value, ACPI_PM1_CONTROL_PRESERVED_BITS, ReadValue); 784167802Sjkim 785167802Sjkim /* Now we can write the data */ 786167802Sjkim 787167802Sjkim Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT.XPm1aControlBlock); 788167802Sjkim if (ACPI_FAILURE (Status)) 789167802Sjkim { 790167802Sjkim goto UnlockAndExit; 791167802Sjkim } 792167802Sjkim 793167802Sjkim Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT.XPm1bControlBlock); 79471867Smsmith break; 79569450Smsmith 79669450Smsmith 79791116Smsmith case ACPI_REGISTER_PM1A_CONTROL: /* 16-bit access */ 79869450Smsmith 799167802Sjkim Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT.XPm1aControlBlock); 80069450Smsmith break; 80169450Smsmith 80269450Smsmith 80391116Smsmith case ACPI_REGISTER_PM1B_CONTROL: /* 16-bit access */ 80471867Smsmith 805167802Sjkim Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT.XPm1bControlBlock); 80671867Smsmith break; 80771867Smsmith 80871867Smsmith 80991116Smsmith case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */ 81069450Smsmith 811167802Sjkim Status = AcpiHwLowLevelWrite (8, Value, &AcpiGbl_FADT.XPm2ControlBlock); 81269450Smsmith break; 81369450Smsmith 81469450Smsmith 81591116Smsmith case ACPI_REGISTER_PM_TIMER: /* 32-bit access */ 81669450Smsmith 817167802Sjkim Status = AcpiHwLowLevelWrite (32, Value, &AcpiGbl_FADT.XPmTimerBlock); 81869450Smsmith break; 81969450Smsmith 82069450Smsmith 82191116Smsmith case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */ 82269450Smsmith 82391116Smsmith /* SMI_CMD is currently always in IO space */ 82469450Smsmith 825167802Sjkim Status = AcpiOsWritePort (AcpiGbl_FADT.SmiCommand, Value, 8); 82669450Smsmith break; 82769450Smsmith 82869450Smsmith 82969450Smsmith default: 83099679Siwasaki Status = AE_BAD_PARAMETER; 83169450Smsmith break; 83269450Smsmith } 83369450Smsmith 83499679SiwasakiUnlockAndExit: 83569450Smsmith if (ACPI_MTX_LOCK == UseLock) 83669450Smsmith { 837167802Sjkim AcpiOsReleaseLock (AcpiGbl_HardwareLock, LockFlags); 83869450Smsmith } 83969450Smsmith 84099679Siwasaki return_ACPI_STATUS (Status); 84169450Smsmith} 84269450Smsmith 84369450Smsmith 84469450Smsmith/****************************************************************************** 84569450Smsmith * 84669450Smsmith * FUNCTION: AcpiHwLowLevelRead 84769450Smsmith * 848117521Snjl * PARAMETERS: Width - 8, 16, or 32 849117521Snjl * Value - Where the value is returned 850138287Smarks * Reg - GAS register structure 85169450Smsmith * 852117521Snjl * RETURN: Status 85369450Smsmith * 854138287Smarks * DESCRIPTION: Read from either memory or IO space. 85569450Smsmith * 85669450Smsmith ******************************************************************************/ 85769450Smsmith 85899679SiwasakiACPI_STATUS 85969450SmsmithAcpiHwLowLevelRead ( 86069450Smsmith UINT32 Width, 86199679Siwasaki UINT32 *Value, 862117521Snjl ACPI_GENERIC_ADDRESS *Reg) 86369450Smsmith{ 864138287Smarks UINT64 Address; 86599679Siwasaki ACPI_STATUS Status; 86669450Smsmith 86769450Smsmith 868167802Sjkim ACPI_FUNCTION_NAME (HwLowLevelRead); 86983174Smsmith 87083174Smsmith 87169450Smsmith /* 87269450Smsmith * Must have a valid pointer to a GAS structure, and 87399679Siwasaki * a non-zero address within. However, don't return an error 87499679Siwasaki * because the PM1A/B code must not fail if B isn't present. 87569450Smsmith */ 876138287Smarks if (!Reg) 87769450Smsmith { 87899679Siwasaki return (AE_OK); 87969450Smsmith } 880138287Smarks 881167802Sjkim /* Get a local copy of the address. Handles possible alignment issues */ 882138287Smarks 883138287Smarks ACPI_MOVE_64_TO_64 (&Address, &Reg->Address); 884167802Sjkim if (!Address) 885138287Smarks { 886138287Smarks return (AE_OK); 887138287Smarks } 88899679Siwasaki *Value = 0; 88969450Smsmith 89069450Smsmith /* 891138287Smarks * Two address spaces supported: Memory or IO. 892138287Smarks * PCI_Config is not supported here because the GAS struct is insufficient 89369450Smsmith */ 894167802Sjkim switch (Reg->SpaceId) 89569450Smsmith { 89677424Smsmith case ACPI_ADR_SPACE_SYSTEM_MEMORY: 89769450Smsmith 898117521Snjl Status = AcpiOsReadMemory ( 899167802Sjkim (ACPI_PHYSICAL_ADDRESS) Address, Value, Width); 90069450Smsmith break; 90169450Smsmith 90269450Smsmith 90377424Smsmith case ACPI_ADR_SPACE_SYSTEM_IO: 90469450Smsmith 905167802Sjkim Status = AcpiOsReadPort ((ACPI_IO_ADDRESS) Address, Value, Width); 90669450Smsmith break; 90769450Smsmith 90869450Smsmith 90999679Siwasaki default: 910167802Sjkim ACPI_ERROR ((AE_INFO, 911167802Sjkim "Unsupported address space: %X", Reg->SpaceId)); 912117521Snjl return (AE_BAD_PARAMETER); 91369450Smsmith } 91469450Smsmith 915151937Sjkim ACPI_DEBUG_PRINT ((ACPI_DB_IO, 916151937Sjkim "Read: %8.8X width %2d from %8.8X%8.8X (%s)\n", 917167802Sjkim *Value, Width, ACPI_FORMAT_UINT64 (Address), 918167802Sjkim AcpiUtGetRegionName (Reg->SpaceId))); 919117521Snjl 92099679Siwasaki return (Status); 92169450Smsmith} 92269450Smsmith 92369450Smsmith 92469450Smsmith/****************************************************************************** 92569450Smsmith * 92669450Smsmith * FUNCTION: AcpiHwLowLevelWrite 92769450Smsmith * 92869450Smsmith * PARAMETERS: Width - 8, 16, or 32 92969450Smsmith * Value - To be written 930138287Smarks * Reg - GAS register structure 93169450Smsmith * 932117521Snjl * RETURN: Status 93369450Smsmith * 934138287Smarks * DESCRIPTION: Write to either memory or IO space. 93569450Smsmith * 93669450Smsmith ******************************************************************************/ 93769450Smsmith 93899679SiwasakiACPI_STATUS 93969450SmsmithAcpiHwLowLevelWrite ( 94069450Smsmith UINT32 Width, 94169450Smsmith UINT32 Value, 942117521Snjl ACPI_GENERIC_ADDRESS *Reg) 94369450Smsmith{ 944138287Smarks UINT64 Address; 94599679Siwasaki ACPI_STATUS Status; 94669450Smsmith 94769450Smsmith 948167802Sjkim ACPI_FUNCTION_NAME (HwLowLevelWrite); 94983174Smsmith 95083174Smsmith 95169450Smsmith /* 95269450Smsmith * Must have a valid pointer to a GAS structure, and 95399679Siwasaki * a non-zero address within. However, don't return an error 95499679Siwasaki * because the PM1A/B code must not fail if B isn't present. 95569450Smsmith */ 956138287Smarks if (!Reg) 95769450Smsmith { 95899679Siwasaki return (AE_OK); 95969450Smsmith } 960123315Snjl 961167802Sjkim /* Get a local copy of the address. Handles possible alignment issues */ 962138287Smarks 963138287Smarks ACPI_MOVE_64_TO_64 (&Address, &Reg->Address); 964167802Sjkim if (!Address) 965138287Smarks { 966138287Smarks return (AE_OK); 967138287Smarks } 968138287Smarks 96969450Smsmith /* 970138287Smarks * Two address spaces supported: Memory or IO. 971138287Smarks * PCI_Config is not supported here because the GAS struct is insufficient 97269450Smsmith */ 973167802Sjkim switch (Reg->SpaceId) 97469450Smsmith { 97577424Smsmith case ACPI_ADR_SPACE_SYSTEM_MEMORY: 97669450Smsmith 977117521Snjl Status = AcpiOsWriteMemory ( 978167802Sjkim (ACPI_PHYSICAL_ADDRESS) Address, Value, Width); 97969450Smsmith break; 98069450Smsmith 98169450Smsmith 98277424Smsmith case ACPI_ADR_SPACE_SYSTEM_IO: 98369450Smsmith 984167802Sjkim Status = AcpiOsWritePort ( 985167802Sjkim (ACPI_IO_ADDRESS) Address, Value, Width); 98669450Smsmith break; 98769450Smsmith 98869450Smsmith 98999679Siwasaki default: 990167802Sjkim ACPI_ERROR ((AE_INFO, 991167802Sjkim "Unsupported address space: %X", Reg->SpaceId)); 992117521Snjl return (AE_BAD_PARAMETER); 99369450Smsmith } 99499679Siwasaki 995151937Sjkim ACPI_DEBUG_PRINT ((ACPI_DB_IO, 996151937Sjkim "Wrote: %8.8X width %2d to %8.8X%8.8X (%s)\n", 997167802Sjkim Value, Width, ACPI_FORMAT_UINT64 (Address), 998167802Sjkim AcpiUtGetRegionName (Reg->SpaceId))); 999117521Snjl 100099679Siwasaki return (Status); 100169450Smsmith} 1002