1 /******************************************************************************
2  *
3  * Module Name: exsystem - Interface to OS services
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2016, 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 #include "acpi.h"
45 #include "accommon.h"
46 #include "acinterp.h"
47 
48 #define _COMPONENT          ACPI_EXECUTER
49         ACPI_MODULE_NAME    ("exsystem")
50 
51 
52 /*******************************************************************************
53  *
54  * FUNCTION:    AcpiExSystemWaitSemaphore
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 before waiting.
64  *
65  ******************************************************************************/
66 
67 ACPI_STATUS
68 AcpiExSystemWaitSemaphore (
69     ACPI_SEMAPHORE          Semaphore,
70     UINT16                  Timeout)
71 {
72     ACPI_STATUS             Status;
73 
74 
75     ACPI_FUNCTION_TRACE (ExSystemWaitSemaphore);
76 
77 
78     Status = AcpiOsWaitSemaphore (Semaphore, 1, ACPI_DO_NOT_WAIT);
79     if (ACPI_SUCCESS (Status))
80     {
81         return_ACPI_STATUS (Status);
82     }
83 
84     if (Status == AE_TIME)
85     {
86         /* We must wait, so unlock the interpreter */
87 
88         AcpiExExitInterpreter ();
89         Status = AcpiOsWaitSemaphore (Semaphore, 1, Timeout);
90 
91         ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
92             "*** Thread awake after blocking, %s\n",
93             AcpiFormatException (Status)));
94 
95         /* Reacquire the interpreter */
96 
97        AcpiExEnterInterpreter ();
98     }
99 
100     return_ACPI_STATUS (Status);
101 }
102 
103 
104 /*******************************************************************************
105  *
106  * FUNCTION:    AcpiExSystemWaitMutex
107  *
108  * PARAMETERS:  Mutex           - Mutex to wait on
109  *              Timeout         - Max time to wait
110  *
111  * RETURN:      Status
112  *
113  * DESCRIPTION: Implements a mutex wait with a check to see if the
114  *              mutex is available immediately. If it is not, the
115  *              interpreter is released before waiting.
116  *
117  ******************************************************************************/
118 
119 ACPI_STATUS
120 AcpiExSystemWaitMutex (
121     ACPI_MUTEX              Mutex,
122     UINT16                  Timeout)
123 {
124     ACPI_STATUS             Status;
125 
126 
127     ACPI_FUNCTION_TRACE (ExSystemWaitMutex);
128 
129 
130     Status = AcpiOsAcquireMutex (Mutex, ACPI_DO_NOT_WAIT);
131     if (ACPI_SUCCESS (Status))
132     {
133         return_ACPI_STATUS (Status);
134     }
135 
136     if (Status == AE_TIME)
137     {
138         /* We must wait, so unlock the interpreter */
139 
140         AcpiExExitInterpreter ();
141         Status = AcpiOsAcquireMutex (Mutex, Timeout);
142 
143         ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
144             "*** Thread awake after blocking, %s\n",
145             AcpiFormatException (Status)));
146 
147         /* Reacquire the interpreter */
148 
149         AcpiExEnterInterpreter ();
150     }
151 
152     return_ACPI_STATUS (Status);
153 }
154 
155 
156 /*******************************************************************************
157  *
158  * FUNCTION:    AcpiExSystemDoStall
159  *
160  * PARAMETERS:  HowLong         - The amount of time to stall,
161  *                                in microseconds
162  *
163  * RETURN:      Status
164  *
165  * DESCRIPTION: Suspend running thread for specified amount of time.
166  *              Note: ACPI specification requires that Stall() does not
167  *              relinquish the processor, and delays longer than 100 usec
168  *              should use Sleep() instead. We allow stalls up to 255 usec
169  *              for compatibility with other interpreters and existing BIOSs.
170  *
171  ******************************************************************************/
172 
173 ACPI_STATUS
174 AcpiExSystemDoStall (
175     UINT32                  HowLong)
176 {
177     ACPI_STATUS             Status = AE_OK;
178 
179 
180     ACPI_FUNCTION_ENTRY ();
181 
182 
183     if (HowLong > 255) /* 255 microseconds */
184     {
185         /*
186          * Longer than 255 usec, this is an error
187          *
188          * (ACPI specifies 100 usec as max, but this gives some slack in
189          * order to support existing BIOSs)
190          */
191         ACPI_ERROR ((AE_INFO,
192             "Time parameter is too large (%u)", HowLong));
193         Status = AE_AML_OPERAND_VALUE;
194     }
195     else
196     {
197         AcpiOsStall (HowLong);
198     }
199 
200     return (Status);
201 }
202 
203 
204 /*******************************************************************************
205  *
206  * FUNCTION:    AcpiExSystemDoSleep
207  *
208  * PARAMETERS:  HowLong         - The amount of time to sleep,
209  *                                in milliseconds
210  *
211  * RETURN:      None
212  *
213  * DESCRIPTION: Sleep the running thread for specified amount of time.
214  *
215  ******************************************************************************/
216 
217 ACPI_STATUS
218 AcpiExSystemDoSleep (
219     UINT64                  HowLong)
220 {
221     ACPI_FUNCTION_ENTRY ();
222 
223 
224     /* Since this thread will sleep, we must release the interpreter */
225 
226     AcpiExExitInterpreter ();
227 
228     /*
229      * For compatibility with other ACPI implementations and to prevent
230      * accidental deep sleeps, limit the sleep time to something reasonable.
231      */
232     if (HowLong > ACPI_MAX_SLEEP)
233     {
234         HowLong = ACPI_MAX_SLEEP;
235     }
236 
237     AcpiOsSleep (HowLong);
238 
239     /* And now we must get the interpreter again */
240 
241     AcpiExEnterInterpreter ();
242     return (AE_OK);
243 }
244 
245 
246 /*******************************************************************************
247  *
248  * FUNCTION:    AcpiExSystemSignalEvent
249  *
250  * PARAMETERS:  ObjDesc         - The object descriptor for this op
251  *
252  * RETURN:      Status
253  *
254  * DESCRIPTION: Provides an access point to perform synchronization operations
255  *              within the AML.
256  *
257  ******************************************************************************/
258 
259 ACPI_STATUS
260 AcpiExSystemSignalEvent (
261     ACPI_OPERAND_OBJECT     *ObjDesc)
262 {
263     ACPI_STATUS             Status = AE_OK;
264 
265 
266     ACPI_FUNCTION_TRACE (ExSystemSignalEvent);
267 
268 
269     if (ObjDesc)
270     {
271         Status = AcpiOsSignalSemaphore (ObjDesc->Event.OsSemaphore, 1);
272     }
273 
274     return_ACPI_STATUS (Status);
275 }
276 
277 
278 /*******************************************************************************
279  *
280  * FUNCTION:    AcpiExSystemWaitEvent
281  *
282  * PARAMETERS:  TimeDesc        - The 'time to delay' object descriptor
283  *              ObjDesc         - The object descriptor for this op
284  *
285  * RETURN:      Status
286  *
287  * DESCRIPTION: Provides an access point to perform synchronization operations
288  *              within the AML. This operation is a request to wait for an
289  *              event.
290  *
291  ******************************************************************************/
292 
293 ACPI_STATUS
294 AcpiExSystemWaitEvent (
295     ACPI_OPERAND_OBJECT     *TimeDesc,
296     ACPI_OPERAND_OBJECT     *ObjDesc)
297 {
298     ACPI_STATUS             Status = AE_OK;
299 
300 
301     ACPI_FUNCTION_TRACE (ExSystemWaitEvent);
302 
303 
304     if (ObjDesc)
305     {
306         Status = AcpiExSystemWaitSemaphore (ObjDesc->Event.OsSemaphore,
307             (UINT16) TimeDesc->Integer.Value);
308     }
309 
310     return_ACPI_STATUS (Status);
311 }
312 
313 
314 /*******************************************************************************
315  *
316  * FUNCTION:    AcpiExSystemResetEvent
317  *
318  * PARAMETERS:  ObjDesc         - The object descriptor for this op
319  *
320  * RETURN:      Status
321  *
322  * DESCRIPTION: Reset an event to a known state.
323  *
324  ******************************************************************************/
325 
326 ACPI_STATUS
327 AcpiExSystemResetEvent (
328     ACPI_OPERAND_OBJECT     *ObjDesc)
329 {
330     ACPI_STATUS             Status = AE_OK;
331     ACPI_SEMAPHORE          TempSemaphore;
332 
333 
334     ACPI_FUNCTION_ENTRY ();
335 
336 
337     /*
338      * We are going to simply delete the existing semaphore and
339      * create a new one!
340      */
341     Status = AcpiOsCreateSemaphore (ACPI_NO_UNIT_LIMIT, 0, &TempSemaphore);
342     if (ACPI_SUCCESS (Status))
343     {
344         (void) AcpiOsDeleteSemaphore (ObjDesc->Event.OsSemaphore);
345         ObjDesc->Event.OsSemaphore = TempSemaphore;
346     }
347 
348     return (Status);
349 }
350