hwsleep.c

来自「linux 内核源代码」· C语言 代码 · 共 612 行 · 第 1/2 页

C
612
字号
/****************************************************************************** * * Name: hwsleep.c - ACPI Hardware Sleep/Wake Interface * *****************************************************************************//* * 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 <acpi/acpi.h>#include <acpi/actables.h>#define _COMPONENT          ACPI_HARDWAREACPI_MODULE_NAME("hwsleep")/******************************************************************************* * * FUNCTION:    acpi_set_firmware_waking_vector * * PARAMETERS:  physical_address    - Physical address of ACPI real mode *                                    entry point. * * RETURN:      Status * * DESCRIPTION: Access function for the firmware_waking_vector field in FACS * ******************************************************************************/acpi_statusacpi_set_firmware_waking_vector(acpi_physical_address physical_address){	struct acpi_table_facs *facs;	acpi_status status;	ACPI_FUNCTION_TRACE(acpi_set_firmware_waking_vector);	/* Get the FACS */	status =	    acpi_get_table_by_index(ACPI_TABLE_INDEX_FACS,				    (struct acpi_table_header **)&facs);	if (ACPI_FAILURE(status)) {		return_ACPI_STATUS(status);	}	/* Set the vector */	if ((facs->length < 32) || (!(facs->xfirmware_waking_vector))) {		/*		 * ACPI 1.0 FACS or short table or optional X_ field is zero		 */		facs->firmware_waking_vector = (u32) physical_address;	} else {		/*		 * ACPI 2.0 FACS with valid X_ field		 */		facs->xfirmware_waking_vector = physical_address;	}	return_ACPI_STATUS(AE_OK);}ACPI_EXPORT_SYMBOL(acpi_set_firmware_waking_vector)/******************************************************************************* * * FUNCTION:    acpi_get_firmware_waking_vector * * PARAMETERS:  *physical_address   - Where the contents of *                                    the firmware_waking_vector field of *                                    the FACS will be returned. * * RETURN:      Status, vector * * DESCRIPTION: Access function for the firmware_waking_vector field in FACS * ******************************************************************************/#ifdef ACPI_FUTURE_USAGEacpi_statusacpi_get_firmware_waking_vector(acpi_physical_address * physical_address){	struct acpi_table_facs *facs;	acpi_status status;	ACPI_FUNCTION_TRACE(acpi_get_firmware_waking_vector);	if (!physical_address) {		return_ACPI_STATUS(AE_BAD_PARAMETER);	}	/* Get the FACS */	status =	    acpi_get_table_by_index(ACPI_TABLE_INDEX_FACS,				    (struct acpi_table_header **)&facs);	if (ACPI_FAILURE(status)) {		return_ACPI_STATUS(status);	}	/* Get the vector */	if ((facs->length < 32) || (!(facs->xfirmware_waking_vector))) {		/*		 * ACPI 1.0 FACS or short table or optional X_ field is zero		 */		*physical_address =		    (acpi_physical_address) facs->firmware_waking_vector;	} else {		/*		 * ACPI 2.0 FACS with valid X_ field		 */		*physical_address =		    (acpi_physical_address) facs->xfirmware_waking_vector;	}	return_ACPI_STATUS(AE_OK);}ACPI_EXPORT_SYMBOL(acpi_get_firmware_waking_vector)#endif/******************************************************************************* * * FUNCTION:    acpi_enter_sleep_state_prep * * PARAMETERS:  sleep_state         - Which sleep state to enter * * RETURN:      Status * * DESCRIPTION: Prepare to enter a system sleep state (see ACPI 2.0 spec p 231) *              This function must execute with interrupts enabled. *              We break sleeping into 2 stages so that OSPM can handle *              various OS-specific tasks between the two steps. * ******************************************************************************/acpi_status acpi_enter_sleep_state_prep(u8 sleep_state){	acpi_status status;	struct acpi_object_list arg_list;	union acpi_object arg;	ACPI_FUNCTION_TRACE(acpi_enter_sleep_state_prep);	/*	 * _PSW methods could be run here to enable wake-on keyboard, LAN, etc.	 */	status = acpi_get_sleep_type_data(sleep_state,					  &acpi_gbl_sleep_type_a,					  &acpi_gbl_sleep_type_b);	if (ACPI_FAILURE(status)) {		return_ACPI_STATUS(status);	}	/* Setup parameter object */	arg_list.count = 1;	arg_list.pointer = &arg;	arg.type = ACPI_TYPE_INTEGER;	arg.integer.value = sleep_state;	/* Run the _PTS and _GTS methods */	status = acpi_evaluate_object(NULL, METHOD_NAME__PTS, &arg_list, NULL);	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {		return_ACPI_STATUS(status);	}	status = acpi_evaluate_object(NULL, METHOD_NAME__GTS, &arg_list, NULL);	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {		return_ACPI_STATUS(status);	}	/* Setup the argument to _SST */	switch (sleep_state) {	case ACPI_STATE_S0:		arg.integer.value = ACPI_SST_WORKING;		break;	case ACPI_STATE_S1:	case ACPI_STATE_S2:	case ACPI_STATE_S3:		arg.integer.value = ACPI_SST_SLEEPING;		break;	case ACPI_STATE_S4:		arg.integer.value = ACPI_SST_SLEEP_CONTEXT;		break;	default:		arg.integer.value = ACPI_SST_INDICATOR_OFF;	/* Default is off */		break;	}	/* Set the system indicators to show the desired sleep state. */	status = acpi_evaluate_object(NULL, METHOD_NAME__SST, &arg_list, NULL);	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {		ACPI_EXCEPTION((AE_INFO, status,				"While executing method _SST"));	}	/* Disable/Clear all GPEs */	status = acpi_hw_disable_all_gpes();	return_ACPI_STATUS(status);}ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_prep)/******************************************************************************* * * FUNCTION:    acpi_enter_sleep_state * * PARAMETERS:  sleep_state         - Which sleep state to enter * * RETURN:      Status * * DESCRIPTION: Enter a system sleep state (see ACPI 2.0 spec p 231) *              THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED * ******************************************************************************/acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state){	u32 PM1Acontrol;	u32 PM1Bcontrol;	struct acpi_bit_register_info *sleep_type_reg_info;	struct acpi_bit_register_info *sleep_enable_reg_info;	u32 in_value;	acpi_status status;	ACPI_FUNCTION_TRACE(acpi_enter_sleep_state);	if ((acpi_gbl_sleep_type_a > ACPI_SLEEP_TYPE_MAX) ||	    (acpi_gbl_sleep_type_b > ACPI_SLEEP_TYPE_MAX)) {		ACPI_ERROR((AE_INFO, "Sleep values out of range: A=%X B=%X",			    acpi_gbl_sleep_type_a, acpi_gbl_sleep_type_b));		return_ACPI_STATUS(AE_AML_OPERAND_VALUE);	}	sleep_type_reg_info =	    acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_TYPE_A);	sleep_enable_reg_info =	    acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_ENABLE);	/* Clear wake status */	status = acpi_set_register(ACPI_BITREG_WAKE_STATUS, 1);	if (ACPI_FAILURE(status)) {		return_ACPI_STATUS(status);	}	/* Clear all fixed and general purpose status bits */	status = acpi_hw_clear_acpi_status();	if (ACPI_FAILURE(status)) {		return_ACPI_STATUS(status);	}	/*	 * 2) Enable all wakeup GPEs	 */	status = acpi_hw_disable_all_gpes();	if (ACPI_FAILURE(status)) {		return_ACPI_STATUS(status);	}	acpi_gbl_system_awake_and_running = FALSE;	status = acpi_hw_enable_all_wakeup_gpes();	if (ACPI_FAILURE(status)) {

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?