1 /******************************************************************************
2  *
3  * Module Name: exsystem - Interface to OS services
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2013, Intel Corp.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions, and the following disclaimer,
16  *    without modification.
17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18  *    substantially similar to the "NO WARRANTY" disclaimer below
19  *    ("Disclaimer") and any redistribution must be conditioned upon
20  *    including a substantially similar Disclaimer requirement for further
21  *    binary redistribution.
22  * 3. Neither the names of the above-listed copyright holders nor the names
23  *    of any contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * Alternatively, this software may be distributed under the terms of the
27  * GNU General Public License ("GPL") version 2 as published by the Free
28  * Software Foundation.
29  *
30  * NO WARRANTY
31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41  * POSSIBILITY OF SUCH DAMAGES.
42  */
43 
44 #define __EXSYSTEM_C__
45 
46 #include "acpi.h"
47 #include "accommon.h"
48 #include "acinterp.h"
49 
50 #define _COMPONENT          ACPI_EXECUTER
51         ACPI_MODULE_NAME    ("exsystem")
52 
53 
54 /*******************************************************************************
55  *
56  * FUNCTION:    AcpiExSystemWaitSemaphore
57  *
58  * PARAMETERS:  Semaphore       - Semaphore to wait on
59  *              Timeout         - Max time to wait
60  *
61  * RETURN:      Status
62  *
63  * DESCRIPTION: Implements a semaphore wait with a check to see if the
64  *              semaphore is available immediately. If it is not, the
65  *              interpreter is released before waiting.
66  *
67  ******************************************************************************/
68 
69 ACPI_STATUS
70 AcpiExSystemWaitSemaphore (
71     ACPI_SEMAPHORE          Semaphore,
72     UINT16                  Timeout)
73 {
74     ACPI_STATUS             Status;
75 
76 
77     ACPI_FUNCTION_TRACE (ExSystemWaitSemaphore);
78 
79 
80     Status = AcpiOsWaitSemaphore (Semaphore, 1, ACPI_DO_NOT_WAIT);
81     if (ACPI_SUCCESS (Status))
82     {
83         return_ACPI_STATUS (Status);
84     }
85 
86     if (Status == AE_TIME)
87     {
88         /* We must wait, so unlock the interpreter */
89 
90         AcpiExRelinquishInterpreter ();
91 
92         Status = AcpiOsWaitSemaphore (Semaphore, 1, Timeout);
93 
94         ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
95             "*** Thread awake after blocking, %s\n",
96             AcpiFormatException (Status)));
97 
98         /* Reacquire the interpreter */
99 
100        AcpiExReacquireInterpreter ();
101     }
102 
103     return_ACPI_STATUS (Status);
104 }
105 
106 
107 /*******************************************************************************
108  *
109  * FUNCTION:    AcpiExSystemWaitMutex
110  *
111  * PARAMETERS:  Mutex           - Mutex to wait on
112  *              Timeout         - Max time to wait
113  *
114  * RETURN:      Status
115  *
116  * DESCRIPTION: Implements a mutex wait with a check to see if the
117  *              mutex is available immediately. If it is not, the
118  *              interpreter is released before waiting.
119  *
120  ******************************************************************************/
121 
122 ACPI_STATUS
123 AcpiExSystemWaitMutex (
124     ACPI_MUTEX              Mutex,
125     UINT16                  Timeout)
126 {
127     ACPI_STATUS             Status;
128 
129 
130     ACPI_FUNCTION_TRACE (ExSystemWaitMutex);
131 
132 
133     Status = AcpiOsAcquireMutex (Mutex, ACPI_DO_NOT_WAIT);
134     if (ACPI_SUCCESS (Status))
135     {
136         return_ACPI_STATUS (Status);
137     }
138 
139     if (Status == AE_TIME)
140     {
141         /* We must wait, so unlock the interpreter */
142 
143         AcpiExRelinquishInterpreter ();
144 
145         Status = AcpiOsAcquireMutex (Mutex, Timeout);
146 
147         ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
148             "*** Thread awake after blocking, %s\n",
149             AcpiFormatException (Status)));
150 
151         /* Reacquire the interpreter */
152 
153         AcpiExReacquireInterpreter ();
154     }
155 
156     return_ACPI_STATUS (Status);
157 }
158 
159 
160 /*******************************************************************************
161  *
162  * FUNCTION:    AcpiExSystemDoStall
163  *
164  * PARAMETERS:  HowLong         - The amount of time to stall,
165  *                                in microseconds
166  *
167  * RETURN:      Status
168  *
169  * DESCRIPTION: Suspend running thread for specified amount of time.
170  *              Note: ACPI specification requires that Stall() does not
171  *              relinquish the processor, and delays longer than 100 usec
172  *              should use Sleep() instead. We allow stalls up to 255 usec
173  *              for compatibility with other interpreters and existing BIOSs.
174  *
175  ******************************************************************************/
176 
177 ACPI_STATUS
178 AcpiExSystemDoStall (
179     UINT32                  HowLong)
180 {
181     ACPI_STATUS             Status = AE_OK;
182 
183 
184     ACPI_FUNCTION_ENTRY ();
185 
186 
187     if (HowLong > 255) /* 255 microseconds */
188     {
189         /*
190          * Longer than 255 usec, this is an error
191          *
192          * (ACPI specifies 100 usec as max, but this gives some slack in
193          * order to support existing BIOSs)
194          */
195         ACPI_ERROR ((AE_INFO, "Time parameter is too large (%u)",
196             HowLong));
197         Status = AE_AML_OPERAND_VALUE;
198     }
199     else
200     {
201         AcpiOsStall (HowLong);
202     }
203 
204     return (Status);
205 }
206 
207 
208 /*******************************************************************************
209  *
210  * FUNCTION:    AcpiExSystemDoSleep
211  *
212  * PARAMETERS:  HowLong         - The amount of time to sleep,
213  *                                in milliseconds
214  *
215  * RETURN:      None
216  *
217  * DESCRIPTION: Sleep the running thread for specified amount of time.
218  *
219  ******************************************************************************/
220 
221 ACPI_STATUS
222 AcpiExSystemDoSleep (
223     UINT64                  HowLong)
224 {
225     ACPI_FUNCTION_ENTRY ();
226 
227 
228     /* Since this thread will sleep, we must release the interpreter */
229 
230     AcpiExRelinquishInterpreter ();
231 
232     /*
233      * For compatibility with other ACPI implementations and to prevent
234      * accidental deep sleeps, limit the sleep time to something reasonable.
235      */
236     if (HowLong > ACPI_MAX_SLEEP)
237     {
238         HowLong = ACPI_MAX_SLEEP;
239     }
240 
241     AcpiOsSleep (HowLong);
242 
243     /* And now we must get the interpreter again */
244 
245     AcpiExReacquireInterpreter ();
246     return (AE_OK);
247 }
248 
249 
250 /*******************************************************************************
251  *
252  * FUNCTION:    AcpiExSystemSignalEvent
253  *
254  * PARAMETERS:  ObjDesc         - The object descriptor for this op
255  *
256  * RETURN:      Status
257  *
258  * DESCRIPTION: Provides an access point to perform synchronization operations
259  *              within the AML.
260  *
261  ******************************************************************************/
262 
263 ACPI_STATUS
264 AcpiExSystemSignalEvent (
265     ACPI_OPERAND_OBJECT     *ObjDesc)
266 {
267     ACPI_STATUS             Status = AE_OK;
268 
269 
270     ACPI_FUNCTION_TRACE (ExSystemSignalEvent);
271 
272 
273     if (ObjDesc)
274     {
275         Status = AcpiOsSignalSemaphore (ObjDesc->Event.OsSemaphore, 1);
276     }
277 
278     return_ACPI_STATUS (Status);
279 }
280 
281 
282 /*******************************************************************************
283  *
284  * FUNCTION:    AcpiExSystemWaitEvent
285  *
286  * PARAMETERS:  TimeDesc        - The 'time to delay' object descriptor
287  *              ObjDesc         - The object descriptor for this op
288  *
289  * RETURN:      Status
290  *
291  * DESCRIPTION: Provides an access point to perform synchronization operations
292  *              within the AML. This operation is a request to wait for an
293  *              event.
294  *
295  ******************************************************************************/
296 
297 ACPI_STATUS
298 AcpiExSystemWaitEvent (
299     ACPI_OPERAND_OBJECT     *TimeDesc,
300     ACPI_OPERAND_OBJECT     *ObjDesc)
301 {
302     ACPI_STATUS             Status = AE_OK;
303 
304 
305     ACPI_FUNCTION_TRACE (ExSystemWaitEvent);
306 
307 
308     if (ObjDesc)
309     {
310         Status = AcpiExSystemWaitSemaphore (ObjDesc->Event.OsSemaphore,
311                     (UINT16) TimeDesc->Integer.Value);
312     }
313 
314     return_ACPI_STATUS (Status);
315 }
316 
317 
318 /*******************************************************************************
319  *
320  * FUNCTION:    AcpiExSystemResetEvent
321  *
322  * PARAMETERS:  ObjDesc         - The object descriptor for this op
323  *
324  * RETURN:      Status
325  *
326  * DESCRIPTION: Reset an event to a known state.
327  *
328  ******************************************************************************/
329 
330 ACPI_STATUS
331 AcpiExSystemResetEvent (
332     ACPI_OPERAND_OBJECT     *ObjDesc)
333 {
334     ACPI_STATUS             Status = AE_OK;
335     ACPI_SEMAPHORE          TempSemaphore;
336 
337 
338     ACPI_FUNCTION_ENTRY ();
339 
340 
341     /*
342      * We are going to simply delete the existing semaphore and
343      * create a new one!
344      */
345     Status = AcpiOsCreateSemaphore (ACPI_NO_UNIT_LIMIT, 0, &TempSemaphore);
346     if (ACPI_SUCCESS (Status))
347     {
348         (void) AcpiOsDeleteSemaphore (ObjDesc->Event.OsSemaphore);
349         ObjDesc->Event.OsSemaphore = TempSemaphore;
350     }
351 
352     return (Status);
353 }
354