make oldconfig will rebuild these...
[linux-2.4.21-pre4.git] / drivers / acpi / hardware / hwacpi.c
1
2 /******************************************************************************
3  *
4  * Module Name: hwacpi - ACPI Hardware Initialization/Mode Interface
5  *              $Revision: 1.1.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         FUNCTION_TRACE ("Hw_initialize");
57
58
59         /* We must have the ACPI tables by the time we get here */
60
61         if (!acpi_gbl_FADT) {
62                 acpi_gbl_restore_acpi_chipset = FALSE;
63
64                 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No FADT!\n"));
65
66                 return_ACPI_STATUS (AE_NO_ACPI_TABLES);
67         }
68
69         /* Identify current ACPI/legacy mode   */
70
71         switch (acpi_gbl_system_flags & SYS_MODES_MASK) {
72         case (SYS_MODE_ACPI):
73
74                 acpi_gbl_original_mode = SYS_MODE_ACPI;
75                 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "System supports ACPI mode only.\n"));
76                 break;
77
78
79         case (SYS_MODE_LEGACY):
80
81                 acpi_gbl_original_mode = SYS_MODE_LEGACY;
82                 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
83                         "Tables loaded from buffer, hardware assumed to support LEGACY mode only.\n"));
84                 break;
85
86
87         case (SYS_MODE_ACPI | SYS_MODE_LEGACY):
88
89                 if (acpi_hw_get_mode () == SYS_MODE_ACPI) {
90                         acpi_gbl_original_mode = SYS_MODE_ACPI;
91                 }
92                 else {
93                         acpi_gbl_original_mode = SYS_MODE_LEGACY;
94                 }
95
96                 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
97                         "System supports both ACPI and LEGACY modes.\n"));
98
99                 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
100                         "System is currently in %s mode.\n",
101                         (acpi_gbl_original_mode == SYS_MODE_ACPI) ? "ACPI" : "LEGACY"));
102                 break;
103         }
104
105
106         if (acpi_gbl_system_flags & SYS_MODE_ACPI) {
107                 /* Target system supports ACPI mode */
108
109                 /*
110                  * The purpose of this code is to save the initial state
111                  * of the ACPI event enable registers. An exit function will be
112                  * registered which will restore this state when the application
113                  * exits. The exit function will also clear all of the ACPI event
114                  * status bits prior to restoring the original mode.
115                  *
116                  * The location of the PM1a_evt_blk enable registers is defined as the
117                  * base of PM1a_evt_blk + DIV_2(PM1a_evt_blk_length). Since the spec further
118                  * fully defines the PM1a_evt_blk to be a total of 4 bytes, the offset
119                  * for the enable registers is always 2 from the base. It is hard
120                  * coded here. If this changes in the spec, this code will need to
121                  * be modified. The PM1b_evt_blk behaves as expected.
122                  */
123                 acpi_gbl_pm1_enable_register_save = (u16) acpi_hw_register_read (
124                                    ACPI_MTX_LOCK, PM1_EN);
125
126
127                 /*
128                  * The GPEs behave similarly, except that the length of the register
129                  * block is not fixed, so the buffer must be allocated with malloc
130                  */
131                 if (ACPI_VALID_ADDRESS (acpi_gbl_FADT->Xgpe0blk.address) &&
132                         acpi_gbl_FADT->gpe0blk_len) {
133                         /* GPE0 specified in FADT  */
134
135                         acpi_gbl_gpe0enable_register_save = ACPI_MEM_ALLOCATE (
136                                            DIV_2 (acpi_gbl_FADT->gpe0blk_len));
137                         if (!acpi_gbl_gpe0enable_register_save) {
138                                 return_ACPI_STATUS (AE_NO_MEMORY);
139                         }
140
141                         /* Save state of GPE0 enable bits */
142
143                         for (index = 0; index < DIV_2 (acpi_gbl_FADT->gpe0blk_len); index++) {
144                                 acpi_gbl_gpe0enable_register_save[index] =
145                                         (u8) acpi_hw_register_read (ACPI_MTX_LOCK, GPE0_EN_BLOCK | index);
146                         }
147                 }
148
149                 else {
150                         acpi_gbl_gpe0enable_register_save = NULL;
151                 }
152
153                 if (ACPI_VALID_ADDRESS (acpi_gbl_FADT->Xgpe1_blk.address) &&
154                         acpi_gbl_FADT->gpe1_blk_len) {
155                         /* GPE1 defined */
156
157                         acpi_gbl_gpe1_enable_register_save = ACPI_MEM_ALLOCATE (
158                                            DIV_2 (acpi_gbl_FADT->gpe1_blk_len));
159                         if (!acpi_gbl_gpe1_enable_register_save) {
160                                 return_ACPI_STATUS (AE_NO_MEMORY);
161                         }
162
163                         /* save state of GPE1 enable bits */
164
165                         for (index = 0; index < DIV_2 (acpi_gbl_FADT->gpe1_blk_len); index++) {
166                                 acpi_gbl_gpe1_enable_register_save[index] =
167                                         (u8) acpi_hw_register_read (ACPI_MTX_LOCK, GPE1_EN_BLOCK | index);
168                         }
169                 }
170
171                 else {
172                         acpi_gbl_gpe1_enable_register_save = NULL;
173                 }
174         }
175
176         return_ACPI_STATUS (status);
177 }
178
179
180 /******************************************************************************
181  *
182  * FUNCTION:    Acpi_hw_set_mode
183  *
184  * PARAMETERS:  Mode            - SYS_MODE_ACPI or SYS_MODE_LEGACY
185  *
186  * RETURN:      Status
187  *
188  * DESCRIPTION: Transitions the system into the requested mode or does nothing
189  *              if the system is already in that mode.
190  *
191  ******************************************************************************/
192
193 acpi_status
194 acpi_hw_set_mode (
195         u32                     mode)
196 {
197
198         acpi_status             status = AE_NO_HARDWARE_RESPONSE;
199
200
201         FUNCTION_TRACE ("Hw_set_mode");
202
203
204         if (mode == SYS_MODE_ACPI) {
205                 /* BIOS should have disabled ALL fixed and GP events */
206
207                 acpi_os_write_port (acpi_gbl_FADT->smi_cmd, acpi_gbl_FADT->acpi_enable, 8);
208                 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Attempting to enable ACPI mode\n"));
209         }
210
211         else if (mode == SYS_MODE_LEGACY) {
212                 /*
213                  * BIOS should clear all fixed status bits and restore fixed event
214                  * enable bits to default
215                  */
216                 acpi_os_write_port (acpi_gbl_FADT->smi_cmd, acpi_gbl_FADT->acpi_disable, 8);
217                 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
218                                  "Attempting to enable Legacy (non-ACPI) mode\n"));
219         }
220
221         /* Give the platform some time to react */
222
223         acpi_os_stall (20000);
224
225         if (acpi_hw_get_mode () == mode) {
226                 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Mode %X successfully enabled\n", mode));
227                 status = AE_OK;
228         }
229
230         return_ACPI_STATUS (status);
231 }
232
233
234 /******************************************************************************
235  *
236  * FUNCTION:    Acpi_hw_get_mode
237  *
238  * PARAMETERS:  none
239  *
240  * RETURN:      SYS_MODE_ACPI or SYS_MODE_LEGACY
241  *
242  * DESCRIPTION: Return current operating state of system.  Determined by
243  *              querying the SCI_EN bit.
244  *
245  ******************************************************************************/
246
247 u32
248 acpi_hw_get_mode (void)
249 {
250
251         FUNCTION_TRACE ("Hw_get_mode");
252
253
254         if (acpi_hw_register_bit_access (ACPI_READ, ACPI_MTX_LOCK, SCI_EN)) {
255                 return_VALUE (SYS_MODE_ACPI);
256         }
257         else {
258                 return_VALUE (SYS_MODE_LEGACY);
259         }
260 }
261
262
263 /******************************************************************************
264  *
265  * FUNCTION:    Acpi_hw_get_mode_capabilities
266  *
267  * PARAMETERS:  none
268  *
269  * RETURN:      logical OR of SYS_MODE_ACPI and SYS_MODE_LEGACY determined at initial
270  *              system state.
271  *
272  * DESCRIPTION: Returns capablities of system
273  *
274  ******************************************************************************/
275
276 u32
277 acpi_hw_get_mode_capabilities (void)
278 {
279
280         FUNCTION_TRACE ("Hw_get_mode_capabilities");
281
282
283         if (!(acpi_gbl_system_flags & SYS_MODES_MASK)) {
284                 if (acpi_hw_get_mode () == SYS_MODE_LEGACY) {
285                         /*
286                          * Assume that if this call is being made, Acpi_init has been called
287                          * and ACPI support has been established by the presence of the
288                          * tables.  Therefore since we're in SYS_MODE_LEGACY, the system
289                          * must support both modes
290                          */
291                         acpi_gbl_system_flags |= (SYS_MODE_ACPI | SYS_MODE_LEGACY);
292                 }
293
294                 else {
295                         /* TBD: [Investigate] !!! this may be unsafe... */
296                         /*
297                          * system is is ACPI mode, so try to switch back to LEGACY to see if
298                          * it is supported
299                          */
300                         acpi_hw_set_mode (SYS_MODE_LEGACY);
301
302                         if (acpi_hw_get_mode () == SYS_MODE_LEGACY) {
303                                 /* Now in SYS_MODE_LEGACY, so both are supported */
304
305                                 acpi_gbl_system_flags |= (SYS_MODE_ACPI | SYS_MODE_LEGACY);
306                                 acpi_hw_set_mode (SYS_MODE_ACPI);
307                         }
308
309                         else {
310                                 /* Still in SYS_MODE_ACPI so this must be an ACPI only system */
311
312                                 acpi_gbl_system_flags |= SYS_MODE_ACPI;
313                         }
314                 }
315         }
316
317         return_VALUE (acpi_gbl_system_flags & SYS_MODES_MASK);
318 }
319
320