linux/drivers/acpi/executer/exutils.c
<<
>>
Prefs
   1
   2/******************************************************************************
   3 *
   4 * Module Name: exutils - interpreter/scanner utilities
   5 *
   6 *****************************************************************************/
   7
   8/*
   9 * Copyright (C) 2000 - 2007, 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/*
  46 * DEFINE_AML_GLOBALS is tested in amlcode.h
  47 * to determine whether certain global names should be "defined" or only
  48 * "declared" in the current compilation.  This enhances maintainability
  49 * by enabling a single header file to embody all knowledge of the names
  50 * in question.
  51 *
  52 * Exactly one module of any executable should #define DEFINE_GLOBALS
  53 * before #including the header files which use this convention.  The
  54 * names in question will be defined and initialized in that module,
  55 * and declared as extern in all other modules which #include those
  56 * header files.
  57 */
  58
  59#define DEFINE_AML_GLOBALS
  60
  61#include <acpi/acpi.h>
  62#include <acpi/acinterp.h>
  63#include <acpi/amlcode.h>
  64#include <acpi/acevents.h>
  65
  66#define _COMPONENT          ACPI_EXECUTER
  67ACPI_MODULE_NAME("exutils")
  68
  69/* Local prototypes */
  70static u32 acpi_ex_digits_needed(acpi_integer value, u32 base);
  71
  72#ifndef ACPI_NO_METHOD_EXECUTION
  73/*******************************************************************************
  74 *
  75 * FUNCTION:    acpi_ex_enter_interpreter
  76 *
  77 * PARAMETERS:  None
  78 *
  79 * RETURN:      None
  80 *
  81 * DESCRIPTION: Enter the interpreter execution region. Failure to enter
  82 *              the interpreter region is a fatal system error. Used in
  83 *              conjunction with exit_interpreter.
  84 *
  85 ******************************************************************************/
  86
  87void acpi_ex_enter_interpreter(void)
  88{
  89        acpi_status status;
  90
  91        ACPI_FUNCTION_TRACE(ex_enter_interpreter);
  92
  93        status = acpi_ut_acquire_mutex(ACPI_MTX_INTERPRETER);
  94        if (ACPI_FAILURE(status)) {
  95                ACPI_ERROR((AE_INFO,
  96                            "Could not acquire AML Interpreter mutex"));
  97        }
  98
  99        return_VOID;
 100}
 101
 102/*******************************************************************************
 103 *
 104 * FUNCTION:    acpi_ex_reacquire_interpreter
 105 *
 106 * PARAMETERS:  None
 107 *
 108 * RETURN:      None
 109 *
 110 * DESCRIPTION: Reacquire the interpreter execution region from within the
 111 *              interpreter code. Failure to enter the interpreter region is a
 112 *              fatal system error. Used in  conjuction with
 113 *              relinquish_interpreter
 114 *
 115 ******************************************************************************/
 116
 117void acpi_ex_reacquire_interpreter(void)
 118{
 119        ACPI_FUNCTION_TRACE(ex_reacquire_interpreter);
 120
 121        /*
 122         * If the global serialized flag is set, do not release the interpreter,
 123         * since it was not actually released by acpi_ex_relinquish_interpreter.
 124         * This forces the interpreter to be single threaded.
 125         */
 126        if (!acpi_gbl_all_methods_serialized) {
 127                acpi_ex_enter_interpreter();
 128        }
 129
 130        return_VOID;
 131}
 132
 133/*******************************************************************************
 134 *
 135 * FUNCTION:    acpi_ex_exit_interpreter
 136 *
 137 * PARAMETERS:  None
 138 *
 139 * RETURN:      None
 140 *
 141 * DESCRIPTION: Exit the interpreter execution region. This is the top level
 142 *              routine used to exit the interpreter when all processing has
 143 *              been completed.
 144 *
 145 ******************************************************************************/
 146
 147void acpi_ex_exit_interpreter(void)
 148{
 149        acpi_status status;
 150
 151        ACPI_FUNCTION_TRACE(ex_exit_interpreter);
 152
 153        status = acpi_ut_release_mutex(ACPI_MTX_INTERPRETER);
 154        if (ACPI_FAILURE(status)) {
 155                ACPI_ERROR((AE_INFO,
 156                            "Could not release AML Interpreter mutex"));
 157        }
 158
 159        return_VOID;
 160}
 161
 162/*******************************************************************************
 163 *
 164 * FUNCTION:    acpi_ex_relinquish_interpreter
 165 *
 166 * PARAMETERS:  None
 167 *
 168 * RETURN:      None
 169 *
 170 * DESCRIPTION: Exit the interpreter execution region, from within the
 171 *              interpreter - before attempting an operation that will possibly
 172 *              block the running thread.
 173 *
 174 * Cases where the interpreter is unlocked internally
 175 *      1) Method to be blocked on a Sleep() AML opcode
 176 *      2) Method to be blocked on an Acquire() AML opcode
 177 *      3) Method to be blocked on a Wait() AML opcode
 178 *      4) Method to be blocked to acquire the global lock
 179 *      5) Method to be blocked waiting to execute a serialized control method
 180 *          that is currently executing
 181 *      6) About to invoke a user-installed opregion handler
 182 *
 183 ******************************************************************************/
 184
 185void acpi_ex_relinquish_interpreter(void)
 186{
 187        ACPI_FUNCTION_TRACE(ex_relinquish_interpreter);
 188
 189        /*
 190         * If the global serialized flag is set, do not release the interpreter.
 191         * This forces the interpreter to be single threaded.
 192         */
 193        if (!acpi_gbl_all_methods_serialized) {
 194                acpi_ex_exit_interpreter();
 195        }
 196
 197        return_VOID;
 198}
 199
 200/*******************************************************************************
 201 *
 202 * FUNCTION:    acpi_ex_truncate_for32bit_table
 203 *
 204 * PARAMETERS:  obj_desc        - Object to be truncated
 205 *
 206 * RETURN:      none
 207 *
 208 * DESCRIPTION: Truncate an ACPI Integer to 32 bits if the execution mode is
 209 *              32-bit, as determined by the revision of the DSDT.
 210 *
 211 ******************************************************************************/
 212
 213void acpi_ex_truncate_for32bit_table(union acpi_operand_object *obj_desc)
 214{
 215
 216        ACPI_FUNCTION_ENTRY();
 217
 218        /*
 219         * Object must be a valid number and we must be executing
 220         * a control method
 221         */
 222        if ((!obj_desc) ||
 223            (ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_INTEGER)) {
 224                return;
 225        }
 226
 227        if (acpi_gbl_integer_byte_width == 4) {
 228                /*
 229                 * We are running a method that exists in a 32-bit ACPI table.
 230                 * Truncate the value to 32 bits by zeroing out the upper 32-bit field
 231                 */
 232                obj_desc->integer.value &= (acpi_integer) ACPI_UINT32_MAX;
 233        }
 234}
 235
 236/*******************************************************************************
 237 *
 238 * FUNCTION:    acpi_ex_acquire_global_lock
 239 *
 240 * PARAMETERS:  field_flags           - Flags with Lock rule:
 241 *                                      always_lock or never_lock
 242 *
 243 * RETURN:      TRUE/FALSE indicating whether the lock was actually acquired
 244 *
 245 * DESCRIPTION: Obtain the global lock and keep track of this fact via two
 246 *              methods.  A global variable keeps the state of the lock, and
 247 *              the state is returned to the caller.
 248 *
 249 ******************************************************************************/
 250
 251u8 acpi_ex_acquire_global_lock(u32 field_flags)
 252{
 253        u8 locked = FALSE;
 254        acpi_status status;
 255
 256        ACPI_FUNCTION_TRACE(ex_acquire_global_lock);
 257
 258        /* Only attempt lock if the always_lock bit is set */
 259
 260        if (field_flags & AML_FIELD_LOCK_RULE_MASK) {
 261
 262                /* We should attempt to get the lock, wait forever */
 263
 264                status = acpi_ev_acquire_global_lock(ACPI_WAIT_FOREVER);
 265                if (ACPI_SUCCESS(status)) {
 266                        locked = TRUE;
 267                } else {
 268                        ACPI_EXCEPTION((AE_INFO, status,
 269                                        "Could not acquire Global Lock"));
 270                }
 271        }
 272
 273        return_UINT8(locked);
 274}
 275
 276/*******************************************************************************
 277 *
 278 * FUNCTION:    acpi_ex_release_global_lock
 279 *
 280 * PARAMETERS:  locked_by_me    - Return value from corresponding call to
 281 *                                acquire_global_lock.
 282 *
 283 * RETURN:      None
 284 *
 285 * DESCRIPTION: Release the global lock if it is locked.
 286 *
 287 ******************************************************************************/
 288
 289void acpi_ex_release_global_lock(u8 locked_by_me)
 290{
 291        acpi_status status;
 292
 293        ACPI_FUNCTION_TRACE(ex_release_global_lock);
 294
 295        /* Only attempt unlock if the caller locked it */
 296
 297        if (locked_by_me) {
 298
 299                /* OK, now release the lock */
 300
 301                status = acpi_ev_release_global_lock();
 302                if (ACPI_FAILURE(status)) {
 303
 304                        /* Report the error, but there isn't much else we can do */
 305
 306                        ACPI_EXCEPTION((AE_INFO, status,
 307                                        "Could not release ACPI Global Lock"));
 308                }
 309        }
 310
 311        return_VOID;
 312}
 313
 314/*******************************************************************************
 315 *
 316 * FUNCTION:    acpi_ex_digits_needed
 317 *
 318 * PARAMETERS:  Value           - Value to be represented
 319 *              Base            - Base of representation
 320 *
 321 * RETURN:      The number of digits.
 322 *
 323 * DESCRIPTION: Calculate the number of digits needed to represent the Value
 324 *              in the given Base (Radix)
 325 *
 326 ******************************************************************************/
 327
 328static u32 acpi_ex_digits_needed(acpi_integer value, u32 base)
 329{
 330        u32 num_digits;
 331        acpi_integer current_value;
 332
 333        ACPI_FUNCTION_TRACE(ex_digits_needed);
 334
 335        /* acpi_integer is unsigned, so we don't worry about a '-' prefix */
 336
 337        if (value == 0) {
 338                return_UINT32(1);
 339        }
 340
 341        current_value = value;
 342        num_digits = 0;
 343
 344        /* Count the digits in the requested base */
 345
 346        while (current_value) {
 347                (void)acpi_ut_short_divide(current_value, base, &current_value,
 348                                           NULL);
 349                num_digits++;
 350        }
 351
 352        return_UINT32(num_digits);
 353}
 354
 355/*******************************************************************************
 356 *
 357 * FUNCTION:    acpi_ex_eisa_id_to_string
 358 *
 359 * PARAMETERS:  numeric_id      - EISA ID to be converted
 360 *              out_string      - Where to put the converted string (8 bytes)
 361 *
 362 * RETURN:      None
 363 *
 364 * DESCRIPTION: Convert a numeric EISA ID to string representation
 365 *
 366 ******************************************************************************/
 367
 368void acpi_ex_eisa_id_to_string(u32 numeric_id, char *out_string)
 369{
 370        u32 eisa_id;
 371
 372        ACPI_FUNCTION_ENTRY();
 373
 374        /* Swap ID to big-endian to get contiguous bits */
 375
 376        eisa_id = acpi_ut_dword_byte_swap(numeric_id);
 377
 378        out_string[0] = (char)('@' + (((unsigned long)eisa_id >> 26) & 0x1f));
 379        out_string[1] = (char)('@' + ((eisa_id >> 21) & 0x1f));
 380        out_string[2] = (char)('@' + ((eisa_id >> 16) & 0x1f));
 381        out_string[3] = acpi_ut_hex_to_ascii_char((acpi_integer) eisa_id, 12);
 382        out_string[4] = acpi_ut_hex_to_ascii_char((acpi_integer) eisa_id, 8);
 383        out_string[5] = acpi_ut_hex_to_ascii_char((acpi_integer) eisa_id, 4);
 384        out_string[6] = acpi_ut_hex_to_ascii_char((acpi_integer) eisa_id, 0);
 385        out_string[7] = 0;
 386}
 387
 388/*******************************************************************************
 389 *
 390 * FUNCTION:    acpi_ex_unsigned_integer_to_string
 391 *
 392 * PARAMETERS:  Value           - Value to be converted
 393 *              out_string      - Where to put the converted string (8 bytes)
 394 *
 395 * RETURN:      None, string
 396 *
 397 * DESCRIPTION: Convert a number to string representation. Assumes string
 398 *              buffer is large enough to hold the string.
 399 *
 400 ******************************************************************************/
 401
 402void acpi_ex_unsigned_integer_to_string(acpi_integer value, char *out_string)
 403{
 404        u32 count;
 405        u32 digits_needed;
 406        u32 remainder;
 407
 408        ACPI_FUNCTION_ENTRY();
 409
 410        digits_needed = acpi_ex_digits_needed(value, 10);
 411        out_string[digits_needed] = 0;
 412
 413        for (count = digits_needed; count > 0; count--) {
 414                (void)acpi_ut_short_divide(value, 10, &value, &remainder);
 415                out_string[count - 1] = (char)('0' + remainder);
 416        }
 417}
 418
 419#endif
 420