1 /******************************************************************************
   2  *
   3  * Module Name: exsystem - Interface to OS services
   4  *
   5  *****************************************************************************/
   6 
   7 /*
   8  * Copyright (C) 2000 - 2014, 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 }