merge ROS Shell without integrated explorer part into trunk
[reactos.git] / reactos / drivers / bus / acpi / hardware / hwacpi.c
1
2 /******************************************************************************
3 *
4 * Module Name: hwacpi - ACPI Hardware Initialization/Mode Interface
5 * $Revision: 1.1 $
6 *
7 *****************************************************************************/
8
9 /*
10 * Copyright (C) 2000, 2001 R. Byron Moore
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 */
26
27
28 #include "acpi.h"
29 #include "achware.h"
30
31
32 #define _COMPONENT ACPI_HARDWARE
33 MODULE_NAME ("hwacpi")
34
35
36 /******************************************************************************
37 *
38 * FUNCTION: Acpi_hw_initialize
39 *
40 * PARAMETERS: None
41 *
42 * RETURN: Status
43 *
44 * DESCRIPTION: Initialize and validate various ACPI registers
45 *
46 ******************************************************************************/
47
48 ACPI_STATUS
49 acpi_hw_initialize (
50 void)
51 {
52 ACPI_STATUS status = AE_OK;
53 u32 index;
54
55
56 /* We must have the ACPI tables by the time we get here */
57
58 if (!acpi_gbl_FADT) {
59 acpi_gbl_restore_acpi_chipset = FALSE;
60
61 return (AE_NO_ACPI_TABLES);
62 }
63
64 /* Must support *some* mode! */
65 /*
66 if (!(System_flags & SYS_MODES_MASK))
67 {
68 Restore_acpi_chipset = FALSE;
69
70 return (AE_ERROR);
71 }
72
73 */
74
75
76 switch (acpi_gbl_system_flags & SYS_MODES_MASK) {
77 /* Identify current ACPI/legacy mode */
78
79 case (SYS_MODE_ACPI):
80
81 acpi_gbl_original_mode = SYS_MODE_ACPI;
82 break;
83
84
85 case (SYS_MODE_LEGACY):
86
87 acpi_gbl_original_mode = SYS_MODE_LEGACY;
88 break;
89
90
91 case (SYS_MODE_ACPI | SYS_MODE_LEGACY):
92
93 if (acpi_hw_get_mode () == SYS_MODE_ACPI) {
94 acpi_gbl_original_mode = SYS_MODE_ACPI;
95 }
96 else {
97 acpi_gbl_original_mode = SYS_MODE_LEGACY;
98 }
99
100 break;
101 }
102
103
104 if (acpi_gbl_system_flags & SYS_MODE_ACPI) {
105 /* Target system supports ACPI mode */
106
107 /*
108 * The purpose of this code is to save the initial state
109 * of the ACPI event enable registers. An exit function will be
110 * registered which will restore this state when the application
111 * exits. The exit function will also clear all of the ACPI event
112 * status bits prior to restoring the original mode.
113 *
114 * The location of the PM1a_evt_blk enable registers is defined as the
115 * base of PM1a_evt_blk + DIV_2(PM1a_evt_blk_length). Since the spec further
116 * fully defines the PM1a_evt_blk to be a total of 4 bytes, the offset
117 * for the enable registers is always 2 from the base. It is hard
118 * coded here. If this changes in the spec, this code will need to
119 * be modified. The PM1b_evt_blk behaves as expected.
120 */
121
122 acpi_gbl_pm1_enable_register_save = (u16) acpi_hw_register_read (ACPI_MTX_LOCK, PM1_EN);
123
124
125 /*
126 * The GPEs behave similarly, except that the length of the register
127 * block is not fixed, so the buffer must be allocated with malloc
128 */
129
130 if (ACPI_VALID_ADDRESS (acpi_gbl_FADT->Xgpe0blk.address) &&
131 acpi_gbl_FADT->gpe0blk_len) {
132 /* GPE0 specified in FADT */
133
134 acpi_gbl_gpe0enable_register_save =
135 acpi_cm_allocate (DIV_2 (acpi_gbl_FADT->gpe0blk_len));
136 if (!acpi_gbl_gpe0enable_register_save) {
137 return (AE_NO_MEMORY);
138 }
139
140 /* Save state of GPE0 enable bits */
141
142 for (index = 0; index < DIV_2 (acpi_gbl_FADT->gpe0blk_len); index++) {
143 acpi_gbl_gpe0enable_register_save[index] =
144 (u8) acpi_hw_register_read (ACPI_MTX_LOCK, GPE0_EN_BLOCK | index);
145 }
146 }
147
148 else {
149 acpi_gbl_gpe0enable_register_save = NULL;
150 }
151
152 if (ACPI_VALID_ADDRESS (acpi_gbl_FADT->Xgpe1_blk.address) &&
153 acpi_gbl_FADT->gpe1_blk_len) {
154 /* GPE1 defined */
155
156 acpi_gbl_gpe1_enable_register_save =
157 acpi_cm_allocate (DIV_2 (acpi_gbl_FADT->gpe1_blk_len));
158 if (!acpi_gbl_gpe1_enable_register_save) {
159 return (AE_NO_MEMORY);
160 }
161
162 /* save state of GPE1 enable bits */
163
164 for (index = 0; index < DIV_2 (acpi_gbl_FADT->gpe1_blk_len); index++) {
165 acpi_gbl_gpe1_enable_register_save[index] =
166 (u8) acpi_hw_register_read (ACPI_MTX_LOCK, GPE1_EN_BLOCK | index);
167 }
168 }
169
170 else {
171 acpi_gbl_gpe1_enable_register_save = NULL;
172 }
173 }
174
175 return (status);
176 }
177
178
179 /******************************************************************************
180 *
181 * FUNCTION: Acpi_hw_set_mode
182 *
183 * PARAMETERS: Mode - SYS_MODE_ACPI or SYS_MODE_LEGACY
184 *
185 * RETURN: Status
186 *
187 * DESCRIPTION: Transitions the system into the requested mode or does nothing
188 * if the system is already in that mode.
189 *
190 ******************************************************************************/
191
192 ACPI_STATUS
193 acpi_hw_set_mode (
194 u32 mode)
195 {
196
197 ACPI_STATUS status = AE_NO_HARDWARE_RESPONSE;
198
199
200 if (mode == SYS_MODE_ACPI) {
201 /* BIOS should have disabled ALL fixed and GP events */
202
203 acpi_os_out8 (acpi_gbl_FADT->smi_cmd, acpi_gbl_FADT->acpi_enable);
204 }
205
206 else if (mode == SYS_MODE_LEGACY) {
207 /*
208 * BIOS should clear all fixed status bits and restore fixed event
209 * enable bits to default
210 */
211
212 acpi_os_out8 (acpi_gbl_FADT->smi_cmd, acpi_gbl_FADT->acpi_disable);
213 }
214
215 if (acpi_hw_get_mode () == mode) {
216 status = AE_OK;
217 }
218
219 return (status);
220 }
221
222
223 /******************************************************************************
224 *
225 * FUNCTION: Acpi_hw_get_mode
226 *
227 * PARAMETERS: none
228 *
229 * RETURN: SYS_MODE_ACPI or SYS_MODE_LEGACY
230 *
231 * DESCRIPTION: Return current operating state of system. Determined by
232 * querying the SCI_EN bit.
233 *
234 ******************************************************************************/
235
236 u32
237 acpi_hw_get_mode (void)
238 {
239
240
241 if (acpi_hw_register_bit_access (ACPI_READ, ACPI_MTX_LOCK, SCI_EN)) {
242 return (SYS_MODE_ACPI);
243 }
244 else {
245 return (SYS_MODE_LEGACY);
246 }
247 }
248
249 /******************************************************************************
250 *
251 * FUNCTION: Acpi_hw_get_mode_capabilities
252 *
253 * PARAMETERS: none
254 *
255 * RETURN: logical OR of SYS_MODE_ACPI and SYS_MODE_LEGACY determined at initial
256 * system state.
257 *
258 * DESCRIPTION: Returns capablities of system
259 *
260 ******************************************************************************/
261
262 u32
263 acpi_hw_get_mode_capabilities (void)
264 {
265
266
267 if (!(acpi_gbl_system_flags & SYS_MODES_MASK)) {
268 if (acpi_hw_get_mode () == SYS_MODE_LEGACY) {
269 /*
270 * Assume that if this call is being made, Acpi_init has been called
271 * and ACPI support has been established by the presence of the
272 * tables. Therefore since we're in SYS_MODE_LEGACY, the system
273 * must support both modes
274 */
275
276 acpi_gbl_system_flags |= (SYS_MODE_ACPI | SYS_MODE_LEGACY);
277 }
278
279 else {
280 /* TBD: [Investigate] !!! this may be unsafe... */
281 /*
282 * system is is ACPI mode, so try to switch back to LEGACY to see if
283 * it is supported
284 */
285 acpi_hw_set_mode (SYS_MODE_LEGACY);
286
287 if (acpi_hw_get_mode () == SYS_MODE_LEGACY) {
288 /* Now in SYS_MODE_LEGACY, so both are supported */
289
290 acpi_gbl_system_flags |= (SYS_MODE_ACPI | SYS_MODE_LEGACY);
291 acpi_hw_set_mode (SYS_MODE_ACPI);
292 }
293
294 else {
295 /* Still in SYS_MODE_ACPI so this must be an ACPI only system */
296
297 acpi_gbl_system_flags |= SYS_MODE_ACPI;
298 }
299 }
300 }
301
302 return (acpi_gbl_system_flags & SYS_MODES_MASK);
303 }
304
305