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 + -
显示快捷键?