Merge /spare/repo/linux-2.6/
[linux-2.6] / drivers / acpi / executer / exsystem.c
1
2 /******************************************************************************
3  *
4  * Module Name: exsystem - Interface to OS services
5  *
6  *****************************************************************************/
7
8 /*
9  * Copyright (C) 2000 - 2005, R. Byron Moore
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 #include <acpi/acpi.h>
46 #include <acpi/acinterp.h>
47 #include <acpi/acevents.h>
48
49 #define _COMPONENT          ACPI_EXECUTER
50 ACPI_MODULE_NAME("exsystem")
51
52 /*******************************************************************************
53  *
54  * FUNCTION:    acpi_ex_system_wait_semaphore
55  *
56  * PARAMETERS:  Semaphore       - Semaphore to wait on
57  *              Timeout         - Max time to wait
58  *
59  * RETURN:      Status
60  *
61  * DESCRIPTION: Implements a semaphore wait with a check to see if the
62  *              semaphore is available immediately.  If it is not, the
63  *              interpreter is released.
64  *
65  ******************************************************************************/
66 acpi_status acpi_ex_system_wait_semaphore(acpi_handle semaphore, u16 timeout)
67 {
68         acpi_status status;
69         acpi_status status2;
70
71         ACPI_FUNCTION_TRACE("ex_system_wait_semaphore");
72
73         status = acpi_os_wait_semaphore(semaphore, 1, 0);
74         if (ACPI_SUCCESS(status)) {
75                 return_ACPI_STATUS(status);
76         }
77
78         if (status == AE_TIME) {
79                 /* We must wait, so unlock the interpreter */
80
81                 acpi_ex_exit_interpreter();
82
83                 status = acpi_os_wait_semaphore(semaphore, 1, timeout);
84
85                 ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
86                                   "*** Thread awake after blocking, %s\n",
87                                   acpi_format_exception(status)));
88
89                 /* Reacquire the interpreter */
90
91                 status2 = acpi_ex_enter_interpreter();
92                 if (ACPI_FAILURE(status2)) {
93                         /* Report fatal error, could not acquire interpreter */
94
95                         return_ACPI_STATUS(status2);
96                 }
97         }
98
99         return_ACPI_STATUS(status);
100 }
101
102 /*******************************************************************************
103  *
104  * FUNCTION:    acpi_ex_system_do_stall
105  *
106  * PARAMETERS:  how_long        - The amount of time to stall,
107  *                                in microseconds
108  *
109  * RETURN:      Status
110  *
111  * DESCRIPTION: Suspend running thread for specified amount of time.
112  *              Note: ACPI specification requires that Stall() does not
113  *              relinquish the processor, and delays longer than 100 usec
114  *              should use Sleep() instead.  We allow stalls up to 255 usec
115  *              for compatibility with other interpreters and existing BIOSs.
116  *
117  ******************************************************************************/
118
119 acpi_status acpi_ex_system_do_stall(u32 how_long)
120 {
121         acpi_status status = AE_OK;
122
123         ACPI_FUNCTION_ENTRY();
124
125         if (how_long > 255) {   /* 255 microseconds */
126                 /*
127                  * Longer than 255 usec, this is an error
128                  *
129                  * (ACPI specifies 100 usec as max, but this gives some slack in
130                  * order to support existing BIOSs)
131                  */
132                 ACPI_REPORT_ERROR(("Stall: Time parameter is too large (%d)\n",
133                                    how_long));
134                 status = AE_AML_OPERAND_VALUE;
135         } else {
136                 acpi_os_stall(how_long);
137         }
138
139         return (status);
140 }
141
142 /*******************************************************************************
143  *
144  * FUNCTION:    acpi_ex_system_do_suspend
145  *
146  * PARAMETERS:  how_long        - The amount of time to suspend,
147  *                                in milliseconds
148  *
149  * RETURN:      None
150  *
151  * DESCRIPTION: Suspend running thread for specified amount of time.
152  *
153  ******************************************************************************/
154
155 acpi_status acpi_ex_system_do_suspend(acpi_integer how_long)
156 {
157         acpi_status status;
158
159         ACPI_FUNCTION_ENTRY();
160
161         /* Since this thread will sleep, we must release the interpreter */
162
163         acpi_ex_exit_interpreter();
164
165         acpi_os_sleep(how_long);
166
167         /* And now we must get the interpreter again */
168
169         status = acpi_ex_enter_interpreter();
170         return (status);
171 }
172
173 /*******************************************************************************
174  *
175  * FUNCTION:    acpi_ex_system_acquire_mutex
176  *
177  * PARAMETERS:  time_desc       - The 'time to delay' object descriptor
178  *              obj_desc        - The object descriptor for this op
179  *
180  * RETURN:      Status
181  *
182  * DESCRIPTION: Provides an access point to perform synchronization operations
183  *              within the AML.  This function will cause a lock to be generated
184  *              for the Mutex pointed to by obj_desc.
185  *
186  ******************************************************************************/
187
188 acpi_status
189 acpi_ex_system_acquire_mutex(union acpi_operand_object * time_desc,
190                              union acpi_operand_object * obj_desc)
191 {
192         acpi_status status = AE_OK;
193
194         ACPI_FUNCTION_TRACE_PTR("ex_system_acquire_mutex", obj_desc);
195
196         if (!obj_desc) {
197                 return_ACPI_STATUS(AE_BAD_PARAMETER);
198         }
199
200         /* Support for the _GL_ Mutex object -- go get the global lock */
201
202         if (obj_desc->mutex.semaphore == acpi_gbl_global_lock_semaphore) {
203                 status =
204                     acpi_ev_acquire_global_lock((u16) time_desc->integer.value);
205                 return_ACPI_STATUS(status);
206         }
207
208         status = acpi_ex_system_wait_semaphore(obj_desc->mutex.semaphore,
209                                                (u16) time_desc->integer.value);
210         return_ACPI_STATUS(status);
211 }
212
213 /*******************************************************************************
214  *
215  * FUNCTION:    acpi_ex_system_release_mutex
216  *
217  * PARAMETERS:  obj_desc        - The object descriptor for this op
218  *
219  * RETURN:      Status
220  *
221  * DESCRIPTION: Provides an access point to perform synchronization operations
222  *              within the AML.  This operation is a request to release a
223  *              previously acquired Mutex.  If the Mutex variable is set then
224  *              it will be decremented.
225  *
226  ******************************************************************************/
227
228 acpi_status acpi_ex_system_release_mutex(union acpi_operand_object *obj_desc)
229 {
230         acpi_status status = AE_OK;
231
232         ACPI_FUNCTION_TRACE("ex_system_release_mutex");
233
234         if (!obj_desc) {
235                 return_ACPI_STATUS(AE_BAD_PARAMETER);
236         }
237
238         /* Support for the _GL_ Mutex object -- release the global lock */
239
240         if (obj_desc->mutex.semaphore == acpi_gbl_global_lock_semaphore) {
241                 status = acpi_ev_release_global_lock();
242                 return_ACPI_STATUS(status);
243         }
244
245         status = acpi_os_signal_semaphore(obj_desc->mutex.semaphore, 1);
246         return_ACPI_STATUS(status);
247 }
248
249 /*******************************************************************************
250  *
251  * FUNCTION:    acpi_ex_system_signal_event
252  *
253  * PARAMETERS:  obj_desc        - The object descriptor for this op
254  *
255  * RETURN:      Status
256  *
257  * DESCRIPTION: Provides an access point to perform synchronization operations
258  *              within the AML.
259  *
260  ******************************************************************************/
261
262 acpi_status acpi_ex_system_signal_event(union acpi_operand_object *obj_desc)
263 {
264         acpi_status status = AE_OK;
265
266         ACPI_FUNCTION_TRACE("ex_system_signal_event");
267
268         if (obj_desc) {
269                 status = acpi_os_signal_semaphore(obj_desc->event.semaphore, 1);
270         }
271
272         return_ACPI_STATUS(status);
273 }
274
275 /*******************************************************************************
276  *
277  * FUNCTION:    acpi_ex_system_wait_event
278  *
279  * PARAMETERS:  time_desc       - The 'time to delay' object descriptor
280  *              obj_desc        - The object descriptor for this op
281  *
282  * RETURN:      Status
283  *
284  * DESCRIPTION: Provides an access point to perform synchronization operations
285  *              within the AML.  This operation is a request to wait for an
286  *              event.
287  *
288  ******************************************************************************/
289
290 acpi_status
291 acpi_ex_system_wait_event(union acpi_operand_object *time_desc,
292                           union acpi_operand_object *obj_desc)
293 {
294         acpi_status status = AE_OK;
295
296         ACPI_FUNCTION_TRACE("ex_system_wait_event");
297
298         if (obj_desc) {
299                 status =
300                     acpi_ex_system_wait_semaphore(obj_desc->event.semaphore,
301                                                   (u16) time_desc->integer.
302                                                   value);
303         }
304
305         return_ACPI_STATUS(status);
306 }
307
308 /*******************************************************************************
309  *
310  * FUNCTION:    acpi_ex_system_reset_event
311  *
312  * PARAMETERS:  obj_desc        - The object descriptor for this op
313  *
314  * RETURN:      Status
315  *
316  * DESCRIPTION: Reset an event to a known state.
317  *
318  ******************************************************************************/
319
320 acpi_status acpi_ex_system_reset_event(union acpi_operand_object *obj_desc)
321 {
322         acpi_status status = AE_OK;
323         void *temp_semaphore;
324
325         ACPI_FUNCTION_ENTRY();
326
327         /*
328          * We are going to simply delete the existing semaphore and
329          * create a new one!
330          */
331         status =
332             acpi_os_create_semaphore(ACPI_NO_UNIT_LIMIT, 0, &temp_semaphore);
333         if (ACPI_SUCCESS(status)) {
334                 (void)acpi_os_delete_semaphore(obj_desc->event.semaphore);
335                 obj_desc->event.semaphore = temp_semaphore;
336         }
337
338         return (status);
339 }