utmisc.c
来自「linux 内核源代码」· C语言 代码 · 共 1,081 行 · 第 1/2 页
C
1,081 行
/******************************************************************************* * * Module Name: utmisc - common utility procedures * ******************************************************************************//* * Copyright (C) 2000 - 2007, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions, and the following disclaimer, * without modification. * 2. Redistributions in binary form must reproduce at minimum a disclaimer * substantially similar to the "NO WARRANTY" disclaimer below * ("Disclaimer") and any redistribution must be conditioned upon * including a substantially similar Disclaimer requirement for further * binary redistribution. * 3. Neither the names of the above-listed copyright holders nor the names * of any contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * Alternatively, this software may be distributed under the terms of the * GNU General Public License ("GPL") version 2 as published by the Free * Software Foundation. * * NO WARRANTY * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. */#include <linux/module.h>#include <acpi/acpi.h>#include <acpi/acnamesp.h>#define _COMPONENT ACPI_UTILITIESACPI_MODULE_NAME("utmisc")/******************************************************************************* * * FUNCTION: acpi_ut_validate_exception * * PARAMETERS: Status - The acpi_status code to be formatted * * RETURN: A string containing the exception text. NULL if exception is * not valid. * * DESCRIPTION: This function validates and translates an ACPI exception into * an ASCII string. * ******************************************************************************/const char *acpi_ut_validate_exception(acpi_status status){ acpi_status sub_status; const char *exception = NULL; ACPI_FUNCTION_ENTRY(); /* * Status is composed of two parts, a "type" and an actual code */ sub_status = (status & ~AE_CODE_MASK); switch (status & AE_CODE_MASK) { case AE_CODE_ENVIRONMENTAL: if (sub_status <= AE_CODE_ENV_MAX) { exception = acpi_gbl_exception_names_env[sub_status]; } break; case AE_CODE_PROGRAMMER: if (sub_status <= AE_CODE_PGM_MAX) { exception = acpi_gbl_exception_names_pgm[sub_status - 1]; } break; case AE_CODE_ACPI_TABLES: if (sub_status <= AE_CODE_TBL_MAX) { exception = acpi_gbl_exception_names_tbl[sub_status - 1]; } break; case AE_CODE_AML: if (sub_status <= AE_CODE_AML_MAX) { exception = acpi_gbl_exception_names_aml[sub_status - 1]; } break; case AE_CODE_CONTROL: if (sub_status <= AE_CODE_CTRL_MAX) { exception = acpi_gbl_exception_names_ctrl[sub_status - 1]; } break; default: break; } return (ACPI_CAST_PTR(const char, exception));}/******************************************************************************* * * FUNCTION: acpi_ut_is_aml_table * * PARAMETERS: Table - An ACPI table * * RETURN: TRUE if table contains executable AML; FALSE otherwise * * DESCRIPTION: Check ACPI Signature for a table that contains AML code. * Currently, these are DSDT,SSDT,PSDT. All other table types are * data tables that do not contain AML code. * ******************************************************************************/u8 acpi_ut_is_aml_table(struct acpi_table_header *table){ /* These are the only tables that contain executable AML */ if (ACPI_COMPARE_NAME(table->signature, ACPI_SIG_DSDT) || ACPI_COMPARE_NAME(table->signature, ACPI_SIG_PSDT) || ACPI_COMPARE_NAME(table->signature, ACPI_SIG_SSDT)) { return (TRUE); } return (FALSE);}/******************************************************************************* * * FUNCTION: acpi_ut_allocate_owner_id * * PARAMETERS: owner_id - Where the new owner ID is returned * * RETURN: Status * * DESCRIPTION: Allocate a table or method owner ID. The owner ID is used to * track objects created by the table or method, to be deleted * when the method exits or the table is unloaded. * ******************************************************************************/acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id){ acpi_native_uint i; acpi_native_uint j; acpi_native_uint k; acpi_status status; ACPI_FUNCTION_TRACE(ut_allocate_owner_id); /* Guard against multiple allocations of ID to the same location */ if (*owner_id) { ACPI_ERROR((AE_INFO, "Owner ID [%2.2X] already exists", *owner_id)); return_ACPI_STATUS(AE_ALREADY_EXISTS); } /* Mutex for the global ID mask */ status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } /* * Find a free owner ID, cycle through all possible IDs on repeated * allocations. (ACPI_NUM_OWNERID_MASKS + 1) because first index may have * to be scanned twice. */ for (i = 0, j = acpi_gbl_last_owner_id_index; i < (ACPI_NUM_OWNERID_MASKS + 1); i++, j++) { if (j >= ACPI_NUM_OWNERID_MASKS) { j = 0; /* Wraparound to start of mask array */ } for (k = acpi_gbl_next_owner_id_offset; k < 32; k++) { if (acpi_gbl_owner_id_mask[j] == ACPI_UINT32_MAX) { /* There are no free IDs in this mask */ break; } if (!(acpi_gbl_owner_id_mask[j] & (1 << k))) { /* * Found a free ID. The actual ID is the bit index plus one, * making zero an invalid Owner ID. Save this as the last ID * allocated and update the global ID mask. */ acpi_gbl_owner_id_mask[j] |= (1 << k); acpi_gbl_last_owner_id_index = (u8) j; acpi_gbl_next_owner_id_offset = (u8) (k + 1); /* * Construct encoded ID from the index and bit position * * Note: Last [j].k (bit 255) is never used and is marked * permanently allocated (prevents +1 overflow) */ *owner_id = (acpi_owner_id) ((k + 1) + ACPI_MUL_32(j)); ACPI_DEBUG_PRINT((ACPI_DB_VALUES, "Allocated OwnerId: %2.2X\n", (unsigned int)*owner_id)); goto exit; } } acpi_gbl_next_owner_id_offset = 0; } /* * All owner_ids have been allocated. This typically should * not happen since the IDs are reused after deallocation. The IDs are * allocated upon table load (one per table) and method execution, and * they are released when a table is unloaded or a method completes * execution. * * If this error happens, there may be very deep nesting of invoked control * methods, or there may be a bug where the IDs are not released. */ status = AE_OWNER_ID_LIMIT; ACPI_ERROR((AE_INFO, "Could not allocate new OwnerId (255 max), AE_OWNER_ID_LIMIT")); exit: (void)acpi_ut_release_mutex(ACPI_MTX_CACHES); return_ACPI_STATUS(status);}/******************************************************************************* * * FUNCTION: acpi_ut_release_owner_id * * PARAMETERS: owner_id_ptr - Pointer to a previously allocated owner_iD * * RETURN: None. No error is returned because we are either exiting a * control method or unloading a table. Either way, we would * ignore any error anyway. * * DESCRIPTION: Release a table or method owner ID. Valid IDs are 1 - 255 * ******************************************************************************/void acpi_ut_release_owner_id(acpi_owner_id * owner_id_ptr){ acpi_owner_id owner_id = *owner_id_ptr; acpi_status status; acpi_native_uint index; u32 bit; ACPI_FUNCTION_TRACE_U32(ut_release_owner_id, owner_id); /* Always clear the input owner_id (zero is an invalid ID) */ *owner_id_ptr = 0; /* Zero is not a valid owner_iD */ if (owner_id == 0) { ACPI_ERROR((AE_INFO, "Invalid OwnerId: %2.2X", owner_id)); return_VOID; } /* Mutex for the global ID mask */ status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES); if (ACPI_FAILURE(status)) { return_VOID; } /* Normalize the ID to zero */ owner_id--; /* Decode ID to index/offset pair */ index = ACPI_DIV_32(owner_id); bit = 1 << ACPI_MOD_32(owner_id); /* Free the owner ID only if it is valid */ if (acpi_gbl_owner_id_mask[index] & bit) { acpi_gbl_owner_id_mask[index] ^= bit; } else { ACPI_ERROR((AE_INFO, "Release of non-allocated OwnerId: %2.2X", owner_id + 1)); } (void)acpi_ut_release_mutex(ACPI_MTX_CACHES); return_VOID;}/******************************************************************************* * * FUNCTION: acpi_ut_strupr (strupr) * * PARAMETERS: src_string - The source string to convert * * RETURN: None * * DESCRIPTION: Convert string to uppercase * * NOTE: This is not a POSIX function, so it appears here, not in utclib.c * ******************************************************************************/void acpi_ut_strupr(char *src_string){ char *string; ACPI_FUNCTION_ENTRY(); if (!src_string) { return; } /* Walk entire string, uppercasing the letters */ for (string = src_string; *string; string++) { *string = (char)ACPI_TOUPPER(*string); } return;}/******************************************************************************* * * FUNCTION: acpi_ut_print_string * * PARAMETERS: String - Null terminated ASCII string * max_length - Maximum output length * * RETURN: None * * DESCRIPTION: Dump an ASCII string with support for ACPI-defined escape * sequences. * ******************************************************************************/void acpi_ut_print_string(char *string, u8 max_length){ u32 i; if (!string) { acpi_os_printf("<\"NULL STRING PTR\">"); return; } acpi_os_printf("\""); for (i = 0; string[i] && (i < max_length); i++) { /* Escape sequences */ switch (string[i]) { case 0x07: acpi_os_printf("\\a"); /* BELL */ break; case 0x08: acpi_os_printf("\\b"); /* BACKSPACE */ break; case 0x0C: acpi_os_printf("\\f"); /* FORMFEED */ break; case 0x0A: acpi_os_printf("\\n"); /* LINEFEED */ break; case 0x0D: acpi_os_printf("\\r"); /* CARRIAGE RETURN */ break; case 0x09: acpi_os_printf("\\t"); /* HORIZONTAL TAB */ break; case 0x0B: acpi_os_printf("\\v"); /* VERTICAL TAB */ break; case '\'': /* Single Quote */ case '\"': /* Double Quote */ case '\\': /* Backslash */ acpi_os_printf("\\%c", (int)string[i]); break; default: /* Check for printable character or hex escape */ if (ACPI_IS_PRINT(string[i])) { /* This is a normal character */ acpi_os_printf("%c", (int)string[i]); } else { /* All others will be Hex escapes */ acpi_os_printf("\\x%2.2X", (s32) string[i]); } break; } } acpi_os_printf("\""); if (i == max_length && string[i]) { acpi_os_printf("..."); }}/******************************************************************************* * * FUNCTION: acpi_ut_dword_byte_swap * * PARAMETERS: Value - Value to be converted * * RETURN: u32 integer with bytes swapped * * DESCRIPTION: Convert a 32-bit value to big-endian (swap the bytes) * ******************************************************************************/u32 acpi_ut_dword_byte_swap(u32 value){ union { u32 value; u8 bytes[4]; } out; union { u32 value; u8 bytes[4]; } in; ACPI_FUNCTION_ENTRY(); in.value = value; out.bytes[0] = in.bytes[3]; out.bytes[1] = in.bytes[2]; out.bytes[2] = in.bytes[1]; out.bytes[3] = in.bytes[0]; return (out.value);}/******************************************************************************* * * FUNCTION: acpi_ut_set_integer_width * * PARAMETERS: Revision From DSDT header * * RETURN: None * * DESCRIPTION: Set the global integer bit width based upon the revision * of the DSDT. For Revision 1 and 0, Integers are 32 bits. * For Revision 2 and above, Integers are 64 bits. Yes, this * makes a difference. * ******************************************************************************/void acpi_ut_set_integer_width(u8 revision){ if (revision < 2) { /* 32-bit case */ acpi_gbl_integer_bit_width = 32; acpi_gbl_integer_nybble_width = 8; acpi_gbl_integer_byte_width = 4; } else { /* 64-bit case (ACPI 2.0+) */ acpi_gbl_integer_bit_width = 64; acpi_gbl_integer_nybble_width = 16; acpi_gbl_integer_byte_width = 8; }}#ifdef ACPI_DEBUG_OUTPUT/******************************************************************************* * * FUNCTION: acpi_ut_display_init_pathname * * PARAMETERS: Type - Object type of the node * obj_handle - Handle whose pathname will be displayed * Path - Additional path string to be appended. * (NULL if no extra path) * * RETURN: acpi_status * * DESCRIPTION: Display full pathname of an object, DEBUG ONLY * ******************************************************************************/voidacpi_ut_display_init_pathname(u8 type, struct acpi_namespace_node *obj_handle, char *path){ acpi_status status; struct acpi_buffer buffer; ACPI_FUNCTION_ENTRY(); /* Only print the path if the appropriate debug level is enabled */ if (!(acpi_dbg_level & ACPI_LV_INIT_NAMES)) { return; }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?