1/******************************************************************************
2 *
3 * Module Name: exsystem - Interface to OS services
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2023, 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 MERCHANTABILITY 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
67ACPI_STATUS
68AcpiExSystemWaitSemaphore (
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
119ACPI_STATUS
120AcpiExSystemWaitMutex (
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:  HowLongUs       - 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
173ACPI_STATUS
174AcpiExSystemDoStall (
175    UINT32                  HowLongUs)
176{
177    ACPI_STATUS             Status = AE_OK;
178
179
180    ACPI_FUNCTION_ENTRY ();
181
182
183    if (HowLongUs > 255)
184    {
185        /*
186         * Longer than 255 microseconds, 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)", HowLongUs));
193        Status = AE_AML_OPERAND_VALUE;
194    }
195    else
196    {
197        if (HowLongUs > 100)
198        {
199            ACPI_WARNING ((AE_INFO,
200                "Time parameter %u us > 100 us violating ACPI spec, please fix the firmware.", HowLongUs));
201        }
202        AcpiOsStall (HowLongUs);
203    }
204
205    return (Status);
206}
207
208
209/*******************************************************************************
210 *
211 * FUNCTION:    AcpiExSystemDoSleep
212 *
213 * PARAMETERS:  HowLongMs       - The amount of time to sleep,
214 *                                in milliseconds
215 *
216 * RETURN:      None
217 *
218 * DESCRIPTION: Sleep the running thread for specified amount of time.
219 *
220 ******************************************************************************/
221
222ACPI_STATUS
223AcpiExSystemDoSleep (
224    UINT64                  HowLongMs)
225{
226    ACPI_FUNCTION_ENTRY ();
227
228
229    /* Since this thread will sleep, we must release the interpreter */
230
231    AcpiExExitInterpreter ();
232
233    /*
234     * For compatibility with other ACPI implementations and to prevent
235     * accidental deep sleeps, limit the sleep time to something reasonable.
236     */
237    if (HowLongMs > ACPI_MAX_SLEEP)
238    {
239        HowLongMs = ACPI_MAX_SLEEP;
240    }
241
242    AcpiOsSleep (HowLongMs);
243
244    /* And now we must get the interpreter again */
245
246    AcpiExEnterInterpreter ();
247    return (AE_OK);
248}
249
250
251/*******************************************************************************
252 *
253 * FUNCTION:    AcpiExSystemSignalEvent
254 *
255 * PARAMETERS:  ObjDesc         - The object descriptor for this op
256 *
257 * RETURN:      Status
258 *
259 * DESCRIPTION: Provides an access point to perform synchronization operations
260 *              within the AML.
261 *
262 ******************************************************************************/
263
264ACPI_STATUS
265AcpiExSystemSignalEvent (
266    ACPI_OPERAND_OBJECT     *ObjDesc)
267{
268    ACPI_STATUS             Status = AE_OK;
269
270
271    ACPI_FUNCTION_TRACE (ExSystemSignalEvent);
272
273
274    if (ObjDesc)
275    {
276        Status = AcpiOsSignalSemaphore (ObjDesc->Event.OsSemaphore, 1);
277    }
278
279    return_ACPI_STATUS (Status);
280}
281
282
283/*******************************************************************************
284 *
285 * FUNCTION:    AcpiExSystemWaitEvent
286 *
287 * PARAMETERS:  TimeDesc        - The 'time to delay' object descriptor
288 *              ObjDesc         - The object descriptor for this op
289 *
290 * RETURN:      Status
291 *
292 * DESCRIPTION: Provides an access point to perform synchronization operations
293 *              within the AML. This operation is a request to wait for an
294 *              event.
295 *
296 ******************************************************************************/
297
298ACPI_STATUS
299AcpiExSystemWaitEvent (
300    ACPI_OPERAND_OBJECT     *TimeDesc,
301    ACPI_OPERAND_OBJECT     *ObjDesc)
302{
303    ACPI_STATUS             Status = AE_OK;
304
305
306    ACPI_FUNCTION_TRACE (ExSystemWaitEvent);
307
308
309    if (ObjDesc)
310    {
311        Status = AcpiExSystemWaitSemaphore (ObjDesc->Event.OsSemaphore,
312            (UINT16) TimeDesc->Integer.Value);
313    }
314
315    return_ACPI_STATUS (Status);
316}
317
318
319/*******************************************************************************
320 *
321 * FUNCTION:    AcpiExSystemResetEvent
322 *
323 * PARAMETERS:  ObjDesc         - The object descriptor for this op
324 *
325 * RETURN:      Status
326 *
327 * DESCRIPTION: Reset an event to a known state.
328 *
329 ******************************************************************************/
330
331ACPI_STATUS
332AcpiExSystemResetEvent (
333    ACPI_OPERAND_OBJECT     *ObjDesc)
334{
335    ACPI_STATUS             Status = AE_OK;
336    ACPI_SEMAPHORE          TempSemaphore;
337
338
339    ACPI_FUNCTION_ENTRY ();
340
341
342    /*
343     * We are going to simply delete the existing semaphore and
344     * create a new one!
345     */
346    Status = AcpiOsCreateSemaphore (ACPI_NO_UNIT_LIMIT, 0, &TempSemaphore);
347    if (ACPI_SUCCESS (Status))
348    {
349        (void) AcpiOsDeleteSemaphore (ObjDesc->Event.OsSemaphore);
350        ObjDesc->Event.OsSemaphore = TempSemaphore;
351    }
352
353    return (Status);
354}
355