hwacpi.c revision 85756
1139804Simp
22729Sdfr/******************************************************************************
32729Sdfr *
42729Sdfr * Module Name: hwacpi - ACPI Hardware Initialization/Mode Interface
52729Sdfr *              $Revision: 46 $
62729Sdfr *
72729Sdfr *****************************************************************************/
82729Sdfr
92729Sdfr/******************************************************************************
102729Sdfr *
112729Sdfr * 1. Copyright Notice
122729Sdfr *
132729Sdfr * Some or all of this work - Copyright (c) 1999, 2000, 2001, Intel Corp.
142729Sdfr * All rights reserved.
152729Sdfr *
162729Sdfr * 2. License
172729Sdfr *
182729Sdfr * 2.1. This is your license from Intel Corp. under its intellectual property
19140614Srwatson * rights.  You may have additional license terms from the party that provided
20140614Srwatson * you this software, covering your right to use that party's intellectual
21140614Srwatson * property rights.
22140614Srwatson *
23140614Srwatson * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
24140614Srwatson * copy of the source code appearing in this file ("Covered Code") an
25140614Srwatson * irrevocable, perpetual, worldwide license under Intel's copyrights in the
26140614Srwatson * base code distributed originally by Intel ("Original Intel Code") to copy,
27140614Srwatson * make derivatives, distribute, use and display any portion of the Covered
28140614Srwatson * Code in any form, with the right to sublicense such rights; and
29140614Srwatson *
30140614Srwatson * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
31140614Srwatson * license (with the right to sublicense), under only those claims of Intel
32140614Srwatson * patents that are infringed by the Original Intel Code, to make, use, sell,
33140614Srwatson * offer to sell, and import the Covered Code and derivative works thereof
34140614Srwatson * solely to the minimum extent necessary to exercise the above copyright
35140614Srwatson * license, and in no event shall the patent license extend to any additions
36140614Srwatson * to or modifications of the Original Intel Code.  No other license or right
37140614Srwatson * is granted directly or by implication, estoppel or otherwise;
38140614Srwatson *
39140614Srwatson * The above copyright and patent license is granted only if the following
40140614Srwatson * conditions are met:
41140614Srwatson *
42140614Srwatson * 3. Conditions
43140614Srwatson *
44140614Srwatson * 3.1. Redistribution of Source with Rights to Further Distribute Source.
45140614Srwatson * Redistribution of source code of any substantial portion of the Covered
46140614Srwatson * Code or modification with rights to further distribute source must include
47140614Srwatson * the above Copyright Notice, the above License, this list of Conditions,
48140614Srwatson * and the following Disclaimer and Export Compliance provision.  In addition,
492729Sdfr * Licensee must cause all Covered Code to which Licensee contributes to
50116182Sobrien * contain a file documenting the changes Licensee made to create that Covered
51116182Sobrien * Code and the date of any change.  Licensee must include in that file the
52116182Sobrien * documentation of any changes made by any predecessor Licensee.  Licensee
53194894Sjhb * must include a prominent statement that the modification is derived,
5459839Speter * directly or indirectly, from Original Intel Code.
5559839Speter *
562729Sdfr * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
572729Sdfr * Redistribution of source code of any substantial portion of the Covered
5811626Sbde * Code or modification without rights to further distribute source must
592729Sdfr * include the following Disclaimer and Export Compliance provision in the
60164033Srwatson * documentation and/or other materials provided with distribution.  In
612729Sdfr * addition, Licensee may not authorize further sublicense of source of any
6282607Sdillon * portion of the Covered Code, and must include terms to the effect that the
6382607Sdillon * license from Licensee to its licensee is limited to the intellectual
64129882Sphk * property embodied in the software Licensee provides to its licensee, and
652729Sdfr * not to intellectual property embodied in modifications its licensee may
66220398Strasz * make.
6769449Salfred *
68140839Ssobomax * 3.3. Redistribution of Executable. Redistribution in executable form of any
6911626Sbde * substantial portion of the Covered Code or modification must reproduce the
7059839Speter * above Copyright Notice, and the following Disclaimer and Export Compliance
7159839Speter * provision in the documentation and/or other materials provided with the
7268024Srwatson * distribution.
732729Sdfr *
74163606Srwatson * 3.4. Intel retains all right, title, and interest in and to the Original
75163606Srwatson * Intel Code.
76219028Snetchild *
77219028Snetchild * 3.5. Neither the name Intel nor any other trademark owned or controlled by
7859839Speter * Intel shall be used in advertising or otherwise to promote the sale, use or
7959839Speter * other dealings in products derived from or relating to the Covered Code
80205323Skib * without prior written authorization from Intel.
8192723Salfred *
8292723Salfred * 4. Disclaimer and Export Compliance
8310358Sjulian *
84100523Salfred * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
85100523Salfred * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
86100523Salfred * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
87194575Srdivacky * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
88100523Salfred * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
892729Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
9092723Salfred * PARTICULAR PURPOSE.
912729Sdfr *
9259839Speter * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
9359839Speter * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
9459839Speter * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
9559839Speter * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
9659839Speter * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
9759839Speter * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
9859839Speter * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
9959839Speter * LIMITED REMEDY.
10059839Speter *
10159839Speter * 4.3. Licensee shall not export, either directly or indirectly, any of this
10259839Speter * software or system incorporating such software without first obtaining any
10359839Speter * required license or other approval from the U. S. Department of Commerce or
10459839Speter * any other agency or department of the United States Government.  In the
10559839Speter * event Licensee exports any such software from the United States or
10659839Speter * re-exports any such software from a foreign destination, Licensee shall
10759839Speter * ensure that the distribution and export/re-export of the software is in
10859839Speter * compliance with all laws, regulations, orders, or other restrictions of the
10959839Speter * U.S. Export Administration Regulations. Licensee agrees that neither it nor
11059839Speter * any of its subsidiaries will export/re-export any technical data, process,
11159839Speter * software, or service, directly or indirectly, to any country for which the
11259839Speter * United States government or any agency thereof requires an export license,
11359839Speter * other governmental approval, or letter of assurance, without first obtaining
11459839Speter * such license, approval or letter.
11559839Speter *
11659839Speter *****************************************************************************/
11759839Speter
11859839Speter#define __HWACPI_C__
11959839Speter
12059839Speter#include "acpi.h"
12159839Speter#include "achware.h"
12259839Speter
12359839Speter
12459839Speter#define _COMPONENT          ACPI_HARDWARE
12559839Speter        MODULE_NAME         ("hwacpi")
12659839Speter
12759839Speter
12859839Speter/******************************************************************************
12959839Speter *
13059839Speter * FUNCTION:    AcpiHwInitialize
13159839Speter *
13259839Speter * PARAMETERS:  None
13359839Speter *
13459839Speter * RETURN:      Status
13559839Speter *
13659839Speter * DESCRIPTION: Initialize and validate various ACPI registers
13759839Speter *
13859839Speter ******************************************************************************/
13959839Speter
14059839SpeterACPI_STATUS
14159839SpeterAcpiHwInitialize (
14259839Speter    void)
14359839Speter{
14459839Speter    ACPI_STATUS             Status = AE_OK;
14559839Speter    UINT32                  Index;
14659839Speter
14759839Speter
14859839Speter    FUNCTION_TRACE ("HwInitialize");
14912819Sphk
15012819Sphk
15159839Speter    /* We must have the ACPI tables by the time we get here */
15259839Speter
15359839Speter    if (!AcpiGbl_FADT)
15459839Speter    {
155137613Srwatson        AcpiGbl_RestoreAcpiChipset = FALSE;
156101772Salfred
1572729Sdfr        ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No FADT!\n"));
158205323Skib
159205323Skib        return_ACPI_STATUS (AE_NO_ACPI_TABLES);
160205323Skib    }
161205323Skib
162205323Skib    /* Identify current ACPI/legacy mode   */
163205323Skib
164205323Skib    switch (AcpiGbl_SystemFlags & SYS_MODES_MASK)
165205323Skib    {
166205323Skib    case (SYS_MODE_ACPI):
167205323Skib
168205323Skib        AcpiGbl_OriginalMode = SYS_MODE_ACPI;
169205323Skib        ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "System supports ACPI mode only.\n"));
170205323Skib        break;
171205323Skib
172205323Skib
173205323Skib    case (SYS_MODE_LEGACY):
174205323Skib
175205323Skib        AcpiGbl_OriginalMode = SYS_MODE_LEGACY;
176205323Skib        ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
177205323Skib            "Tables loaded from buffer, hardware assumed to support LEGACY mode only.\n"));
178205323Skib        break;
179205323Skib
180205323Skib
181205323Skib    case (SYS_MODE_ACPI | SYS_MODE_LEGACY):
182205323Skib
183205323Skib        if (AcpiHwGetMode () == SYS_MODE_ACPI)
184205323Skib        {
185205323Skib            AcpiGbl_OriginalMode = SYS_MODE_ACPI;
186205323Skib        }
187205323Skib        else
188205323Skib        {
189205323Skib            AcpiGbl_OriginalMode = SYS_MODE_LEGACY;
190205323Skib        }
191205323Skib
192205323Skib        ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
193205323Skib            "System supports both ACPI and LEGACY modes.\n"));
19469449Salfred
1952729Sdfr        ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
196205323Skib            "System is currently in %s mode.\n",
1972729Sdfr            (AcpiGbl_OriginalMode == SYS_MODE_ACPI) ? "ACPI" : "LEGACY"));
19883765Smr        break;
19983765Smr    }
20083765Smr
20183765Smr
202139436Srwatson    if (AcpiGbl_SystemFlags & SYS_MODE_ACPI)
203139436Srwatson    {
20483765Smr        /* Target system supports ACPI mode */
205111119Simp
206111119Simp        /*
207111119Simp         * The purpose of this code is to save the initial state
208137613Srwatson         * of the ACPI event enable registers. An exit function will be
209137613Srwatson         * registered which will restore this state when the application
21059839Speter         * exits. The exit function will also clear all of the ACPI event
2112729Sdfr         * status bits prior to restoring the original mode.
2122729Sdfr         *
2132729Sdfr         * The location of the PM1aEvtBlk enable registers is defined as the
2142729Sdfr         * base of PM1aEvtBlk + DIV_2(PM1aEvtBlkLength). Since the spec further
2152729Sdfr         * fully defines the PM1aEvtBlk to be a total of 4 bytes, the offset
2162729Sdfr         * for the enable registers is always 2 from the base. It is hard
2172729Sdfr         * coded here. If this changes in the spec, this code will need to
2182729Sdfr         * be modified. The PM1bEvtBlk behaves as expected.
2192729Sdfr         */
2202729Sdfr        AcpiGbl_Pm1EnableRegisterSave = (UINT16) AcpiHwRegisterRead (
221100523Salfred                                                    ACPI_MTX_LOCK, PM1_EN);
222100523Salfred
2232729Sdfr
2242729Sdfr        /*
2252729Sdfr         * The GPEs behave similarly, except that the length of the register
2262729Sdfr         * block is not fixed, so the buffer must be allocated with malloc
227100523Salfred         */
2282729Sdfr        if (ACPI_VALID_ADDRESS (AcpiGbl_FADT->XGpe0Blk.Address) &&
2292729Sdfr            AcpiGbl_FADT->Gpe0BlkLen)
2302729Sdfr        {
2312729Sdfr            /* GPE0 specified in FADT  */
2322729Sdfr
2332729Sdfr            AcpiGbl_Gpe0EnableRegisterSave = ACPI_MEM_ALLOCATE (
2342729Sdfr                                            DIV_2 (AcpiGbl_FADT->Gpe0BlkLen));
2352729Sdfr            if (!AcpiGbl_Gpe0EnableRegisterSave)
2362729Sdfr            {
2372729Sdfr                return_ACPI_STATUS (AE_NO_MEMORY);
2382729Sdfr            }
2392729Sdfr
2402729Sdfr            /* Save state of GPE0 enable bits */
2412729Sdfr
2422729Sdfr            for (Index = 0; Index < DIV_2 (AcpiGbl_FADT->Gpe0BlkLen); Index++)
2432729Sdfr            {
244140614Srwatson                AcpiGbl_Gpe0EnableRegisterSave[Index] =
245172930Srwatson                    (UINT8) AcpiHwRegisterRead (ACPI_MTX_LOCK, GPE0_EN_BLOCK | Index);
246140614Srwatson            }
2472729Sdfr        }
2482729Sdfr
2492729Sdfr        else
2502729Sdfr        {
251137613Srwatson            AcpiGbl_Gpe0EnableRegisterSave = NULL;
252137613Srwatson        }
253137613Srwatson
254140614Srwatson        if (ACPI_VALID_ADDRESS (AcpiGbl_FADT->XGpe1Blk.Address) &&
255172930Srwatson            AcpiGbl_FADT->Gpe1BlkLen)
256140614Srwatson        {
2572729Sdfr            /* GPE1 defined */
258101772Salfred
259205323Skib            AcpiGbl_Gpe1EnableRegisterSave = ACPI_MEM_ALLOCATE (
260205323Skib                                            DIV_2 (AcpiGbl_FADT->Gpe1BlkLen));
261205323Skib            if (!AcpiGbl_Gpe1EnableRegisterSave)
262205323Skib            {
263205323Skib                return_ACPI_STATUS (AE_NO_MEMORY);
264205323Skib            }
265205323Skib
266205323Skib            /* save state of GPE1 enable bits */
267205323Skib
268205323Skib            for (Index = 0; Index < DIV_2 (AcpiGbl_FADT->Gpe1BlkLen); Index++)
2692729Sdfr            {
2702729Sdfr                AcpiGbl_Gpe1EnableRegisterSave[Index] =
27169449Salfred                    (UINT8) AcpiHwRegisterRead (ACPI_MTX_LOCK, GPE1_EN_BLOCK | Index);
27269449Salfred            }
27369449Salfred        }
274137613Srwatson
27569449Salfred        else
276140614Srwatson        {
277140614Srwatson            AcpiGbl_Gpe1EnableRegisterSave = NULL;
278140614Srwatson        }
27969449Salfred    }
280205323Skib
281205323Skib    return_ACPI_STATUS (Status);
282205323Skib}
283205323Skib
284205323Skib
28569449Salfred/******************************************************************************
28669449Salfred *
28769449Salfred * FUNCTION:    AcpiHwSetMode
28869449Salfred *
28969449Salfred * PARAMETERS:  Mode            - SYS_MODE_ACPI or SYS_MODE_LEGACY
29069449Salfred *
29169449Salfred * RETURN:      Status
292137613Srwatson *
293137613Srwatson * DESCRIPTION: Transitions the system into the requested mode or does nothing
294137613Srwatson *              if the system is already in that mode.
29569449Salfred *
29669449Salfred ******************************************************************************/
29769449Salfred
29869449SalfredACPI_STATUS
29969449SalfredAcpiHwSetMode (
300140614Srwatson    UINT32                  Mode)
301140614Srwatson{
302172930Srwatson
303140614Srwatson    ACPI_STATUS             Status = AE_NO_HARDWARE_RESPONSE;
304172930Srwatson
305140614Srwatson
30669449Salfred    FUNCTION_TRACE ("HwSetMode");
30769449Salfred
30869449Salfred
30969449Salfred    if (Mode == SYS_MODE_ACPI)
310101772Salfred    {
31169449Salfred        /* BIOS should have disabled ALL fixed and GP events */
31269449Salfred
31369449Salfred        AcpiOsWritePort (AcpiGbl_FADT->SmiCmd, AcpiGbl_FADT->AcpiEnable, 8);
31469449Salfred        ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Attempting to enable ACPI mode\n"));
31569449Salfred    }
31669449Salfred
31769449Salfred    else if (Mode == SYS_MODE_LEGACY)
31869449Salfred    {
31969449Salfred        /*
32069449Salfred         * BIOS should clear all fixed status bits and restore fixed event
32169449Salfred         * enable bits to default
322205323Skib         */
323205323Skib        AcpiOsWritePort (AcpiGbl_FADT->SmiCmd, AcpiGbl_FADT->AcpiDisable, 8);
324205323Skib        ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
32569449Salfred                    "Attempting to enable Legacy (non-ACPI) mode\n"));
32669449Salfred    }
32769449Salfred
32869449Salfred    /* Give the platform some time to react */
32969449Salfred
33069449Salfred    AcpiOsStall (20000);
33169449Salfred
33269449Salfred    if (AcpiHwGetMode () == Mode)
33369449Salfred    {
33469449Salfred        ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Mode %X successfully enabled\n", Mode));
33569449Salfred        Status = AE_OK;
33669449Salfred    }
33769449Salfred
33871038Sdes    return_ACPI_STATUS (Status);
33971038Sdes}
34069449Salfred
34169449Salfred
34269449Salfred/******************************************************************************
34369449Salfred *
344194832Sjhb * FUNCTION:    AcpiHwGetMode
34571038Sdes *
34669449Salfred * PARAMETERS:  none
3472729Sdfr *
3482729Sdfr * RETURN:      SYS_MODE_ACPI or SYS_MODE_LEGACY
3492729Sdfr *
3502729Sdfr * DESCRIPTION: Return current operating state of system.  Determined by
3512729Sdfr *              querying the SCI_EN bit.
3522729Sdfr *
3532729Sdfr ******************************************************************************/
3542729Sdfr
3552729SdfrUINT32
3562729SdfrAcpiHwGetMode (void)
3572729Sdfr{
3582729Sdfr
3592729Sdfr    FUNCTION_TRACE ("HwGetMode");
3602729Sdfr
3612729Sdfr
3622729Sdfr    if (AcpiHwRegisterBitAccess (ACPI_READ, ACPI_MTX_LOCK, SCI_EN))
3632729Sdfr    {
3642729Sdfr        return_VALUE (SYS_MODE_ACPI);
3652729Sdfr    }
3662729Sdfr    else
3672729Sdfr    {
3682729Sdfr        return_VALUE (SYS_MODE_LEGACY);
369140614Srwatson    }
370172930Srwatson}
371140614Srwatson
3722729Sdfr
3732729Sdfr/******************************************************************************
37412866Speter *
3752729Sdfr * FUNCTION:    AcpiHwGetModeCapabilities
3762729Sdfr *
3772729Sdfr * PARAMETERS:  none
37812866Speter *
3792729Sdfr * RETURN:      logical OR of SYS_MODE_ACPI and SYS_MODE_LEGACY determined at initial
38012866Speter *              system state.
38112866Speter *
38283366Sjulian * DESCRIPTION: Returns capablities of system
38383366Sjulian *
3842729Sdfr ******************************************************************************/
3852729Sdfr
3862729SdfrUINT32
3872729SdfrAcpiHwGetModeCapabilities (void)
3882729Sdfr{
389140839Ssobomax
390140839Ssobomax    FUNCTION_TRACE ("HwGetModeCapabilities");
391165403Sjkim
392140839Ssobomax
393140839Ssobomax    if (!(AcpiGbl_SystemFlags & SYS_MODES_MASK))
394140839Ssobomax    {
395141471Sjhb        if (AcpiHwGetMode () == SYS_MODE_LEGACY)
396140839Ssobomax        {
397141471Sjhb            /*
398140839Ssobomax             * Assume that if this call is being made, AcpiInit has been called
399140839Ssobomax             * and ACPI support has been established by the presence of the
400140839Ssobomax             * tables.  Therefore since we're in SYS_MODE_LEGACY, the system
401140839Ssobomax             * must support both modes
402141471Sjhb             */
403140839Ssobomax            AcpiGbl_SystemFlags |= (SYS_MODE_ACPI | SYS_MODE_LEGACY);
404140839Ssobomax        }
405140839Ssobomax
406140839Ssobomax        else
407140839Ssobomax        {
408140839Ssobomax            /* TBD: [Investigate] !!! this may be unsafe... */
409137613Srwatson            /*
4102729Sdfr             * system is is ACPI mode, so try to switch back to LEGACY to see if
411192895Sjamie             * it is supported
41291703Sjhb             */
41391703Sjhb            AcpiHwSetMode (SYS_MODE_LEGACY);
414140839Ssobomax
4152729Sdfr            if (AcpiHwGetMode () == SYS_MODE_LEGACY)
416140839Ssobomax            {
417140839Ssobomax                /* Now in SYS_MODE_LEGACY, so both are supported */
418100523Salfred
419101772Salfred                AcpiGbl_SystemFlags |= (SYS_MODE_ACPI | SYS_MODE_LEGACY);
4202729Sdfr                AcpiHwSetMode (SYS_MODE_ACPI);
4212729Sdfr            }
422140839Ssobomax
4232729Sdfr            else
424101772Salfred            {
425137613Srwatson                /* Still in SYS_MODE_ACPI so this must be an ACPI only system */
426100523Salfred
42782607Sdillon                AcpiGbl_SystemFlags |= SYS_MODE_ACPI;
42882607Sdillon            }
4292729Sdfr        }
430140839Ssobomax    }
431100523Salfred
43282607Sdillon    return_VALUE (AcpiGbl_SystemFlags & SYS_MODES_MASK);
43382607Sdillon}
4342729Sdfr
435140614Srwatson
436172930Srwatson