1
2/******************************************************************************
3 *
4 * Module Name: hwacpi - ACPI Hardware Initialization/Mode Interface
5 *
6 *****************************************************************************/
7
8/*
9 * Copyright (C) 2000 - 2011, Intel Corp.
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 *    notice, this list of conditions, and the following disclaimer,
17 *    without modification.
18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19 *    substantially similar to the "NO WARRANTY" disclaimer below
20 *    ("Disclaimer") and any redistribution must be conditioned upon
21 *    including a substantially similar Disclaimer requirement for further
22 *    binary redistribution.
23 * 3. Neither the names of the above-listed copyright holders nor the names
24 *    of any contributors may be used to endorse or promote products derived
25 *    from this software without specific prior written permission.
26 *
27 * Alternatively, this software may be distributed under the terms of the
28 * GNU General Public License ("GPL") version 2 as published by the Free
29 * Software Foundation.
30 *
31 * NO WARRANTY
32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42 * POSSIBILITY OF SUCH DAMAGES.
43 */
44
45#define __HWACPI_C__
46
47#include <contrib/dev/acpica/include/acpi.h>
48#include <contrib/dev/acpica/include/accommon.h>
49
50
51#define _COMPONENT          ACPI_HARDWARE
52        ACPI_MODULE_NAME    ("hwacpi")
53
54
55/******************************************************************************
56 *
57 * FUNCTION:    AcpiHwSetMode
58 *
59 * PARAMETERS:  Mode            - SYS_MODE_ACPI or SYS_MODE_LEGACY
60 *
61 * RETURN:      Status
62 *
63 * DESCRIPTION: Transitions the system into the requested mode.
64 *
65 ******************************************************************************/
66
67ACPI_STATUS
68AcpiHwSetMode (
69    UINT32                  Mode)
70{
71
72    ACPI_STATUS             Status;
73    UINT32                  Retry;
74
75
76    ACPI_FUNCTION_TRACE (HwSetMode);
77
78    /*
79     * ACPI 2.0 clarified that if SMI_CMD in FADT is zero,
80     * system does not support mode transition.
81     */
82    if (!AcpiGbl_FADT.SmiCommand)
83    {
84        ACPI_ERROR ((AE_INFO, "No SMI_CMD in FADT, mode transition failed"));
85        return_ACPI_STATUS (AE_NO_HARDWARE_RESPONSE);
86    }
87
88    /*
89     * ACPI 2.0 clarified the meaning of ACPI_ENABLE and ACPI_DISABLE
90     * in FADT: If it is zero, enabling or disabling is not supported.
91     * As old systems may have used zero for mode transition,
92     * we make sure both the numbers are zero to determine these
93     * transitions are not supported.
94     */
95    if (!AcpiGbl_FADT.AcpiEnable && !AcpiGbl_FADT.AcpiDisable)
96    {
97        ACPI_ERROR ((AE_INFO,
98            "No ACPI mode transition supported in this system "
99            "(enable/disable both zero)"));
100        return_ACPI_STATUS (AE_OK);
101    }
102
103    switch (Mode)
104    {
105    case ACPI_SYS_MODE_ACPI:
106
107        /* BIOS should have disabled ALL fixed and GP events */
108
109        Status = AcpiHwWritePort (AcpiGbl_FADT.SmiCommand,
110                        (UINT32) AcpiGbl_FADT.AcpiEnable, 8);
111        ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Attempting to enable ACPI mode\n"));
112        break;
113
114    case ACPI_SYS_MODE_LEGACY:
115
116        /*
117         * BIOS should clear all fixed status bits and restore fixed event
118         * enable bits to default
119         */
120        Status = AcpiHwWritePort (AcpiGbl_FADT.SmiCommand,
121                    (UINT32) AcpiGbl_FADT.AcpiDisable, 8);
122        ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
123                    "Attempting to enable Legacy (non-ACPI) mode\n"));
124        break;
125
126    default:
127        return_ACPI_STATUS (AE_BAD_PARAMETER);
128    }
129
130    if (ACPI_FAILURE (Status))
131    {
132        ACPI_EXCEPTION ((AE_INFO, Status,
133            "Could not write ACPI mode change"));
134        return_ACPI_STATUS (Status);
135    }
136
137    /*
138     * Some hardware takes a LONG time to switch modes. Give them 3 sec to
139     * do so, but allow faster systems to proceed more quickly.
140     */
141    Retry = 3000;
142    while (Retry)
143    {
144        if (AcpiHwGetMode() == Mode)
145        {
146            ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Mode %X successfully enabled\n",
147                Mode));
148            return_ACPI_STATUS (AE_OK);
149        }
150        AcpiOsStall(1000);
151        Retry--;
152    }
153
154    ACPI_ERROR ((AE_INFO, "Hardware did not change modes"));
155    return_ACPI_STATUS (AE_NO_HARDWARE_RESPONSE);
156}
157
158
159/*******************************************************************************
160 *
161 * FUNCTION:    AcpiHwGetMode
162 *
163 * PARAMETERS:  none
164 *
165 * RETURN:      SYS_MODE_ACPI or SYS_MODE_LEGACY
166 *
167 * DESCRIPTION: Return current operating state of system.  Determined by
168 *              querying the SCI_EN bit.
169 *
170 ******************************************************************************/
171
172UINT32
173AcpiHwGetMode (
174    void)
175{
176    ACPI_STATUS             Status;
177    UINT32                  Value;
178
179
180    ACPI_FUNCTION_TRACE (HwGetMode);
181
182
183    /*
184     * ACPI 2.0 clarified that if SMI_CMD in FADT is zero,
185     * system does not support mode transition.
186     */
187    if (!AcpiGbl_FADT.SmiCommand)
188    {
189        return_UINT32 (ACPI_SYS_MODE_ACPI);
190    }
191
192    Status = AcpiReadBitRegister (ACPI_BITREG_SCI_ENABLE, &Value);
193    if (ACPI_FAILURE (Status))
194    {
195        return_UINT32 (ACPI_SYS_MODE_LEGACY);
196    }
197
198    if (Value)
199    {
200        return_UINT32 (ACPI_SYS_MODE_ACPI);
201    }
202    else
203    {
204        return_UINT32 (ACPI_SYS_MODE_LEGACY);
205    }
206}
207