⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hwregs.c

📁 内核linux2.4.20,可跟rtlinux3.2打补丁 组成实时linux系统,编译内核
💻 C
📖 第 1 页 / 共 2 页
字号:
/******************************************************************************* * * Module Name: hwregs - Read/write access functions for the various ACPI *                       control and status registers. *              $Revision: 110 $ * ******************************************************************************//* *  Copyright (C) 2000, 2001 R. Byron Moore * *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 2 of the License, or *  (at your option) any later version. * *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. * *  You should have received a copy of the GNU General Public License *  along with this program; if not, write to the Free Software *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */#include "acpi.h"#include "achware.h"#include "acnamesp.h"#define _COMPONENT          ACPI_HARDWARE	 MODULE_NAME         ("hwregs")/******************************************************************************* * * FUNCTION:    Acpi_hw_get_bit_shift * * PARAMETERS:  Mask            - Input mask to determine bit shift from. *                                Must have at least 1 bit set. * * RETURN:      Bit location of the lsb of the mask * * DESCRIPTION: Returns the bit number for the low order bit that's set. * ******************************************************************************/u32acpi_hw_get_bit_shift (	u32                     mask){	u32                     shift;	FUNCTION_TRACE ("Hw_get_bit_shift");	for (shift = 0; ((mask >> shift) & 1) == 0; shift++) { ; }	return_VALUE (shift);}/******************************************************************************* * * FUNCTION:    Acpi_hw_clear_acpi_status * * PARAMETERS:  none * * RETURN:      none * * DESCRIPTION: Clears all fixed and general purpose status bits * ******************************************************************************/voidacpi_hw_clear_acpi_status (void){	u16                     gpe_length;	u16                     index;	FUNCTION_TRACE ("Hw_clear_acpi_status");	ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %04X to %04X\n",		ALL_FIXED_STS_BITS,		(u16) ACPI_GET_ADDRESS (acpi_gbl_FADT->Xpm1a_evt_blk.address)));	acpi_ut_acquire_mutex (ACPI_MTX_HARDWARE);	acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, PM1_STS, ALL_FIXED_STS_BITS);	if (ACPI_VALID_ADDRESS (acpi_gbl_FADT->Xpm1b_evt_blk.address)) {		acpi_os_write_port ((ACPI_IO_ADDRESS)			ACPI_GET_ADDRESS (acpi_gbl_FADT->Xpm1b_evt_blk.address),			ALL_FIXED_STS_BITS, 16);	}	/* now clear the GPE Bits */	if (acpi_gbl_FADT->gpe0blk_len) {		gpe_length = (u16) DIV_2 (acpi_gbl_FADT->gpe0blk_len);		for (index = 0; index < gpe_length; index++) {			acpi_os_write_port ((ACPI_IO_ADDRESS) (				ACPI_GET_ADDRESS (acpi_gbl_FADT->Xgpe0blk.address) + index),					0xFF, 8);		}	}	if (acpi_gbl_FADT->gpe1_blk_len) {		gpe_length = (u16) DIV_2 (acpi_gbl_FADT->gpe1_blk_len);		for (index = 0; index < gpe_length; index++) {			acpi_os_write_port ((ACPI_IO_ADDRESS) (				ACPI_GET_ADDRESS (acpi_gbl_FADT->Xgpe1_blk.address) + index),				0xFF, 8);		}	}	acpi_ut_release_mutex (ACPI_MTX_HARDWARE);	return_VOID;}/******************************************************************************* * * FUNCTION:    Acpi_hw_obtain_sleep_type_register_data * * PARAMETERS:  Sleep_state       - Numeric state requested *              *Slp_Typ_a         - Pointer to byte to receive SLP_TYPa value *              *Slp_Typ_b         - Pointer to byte to receive SLP_TYPb value * * RETURN:      Status - ACPI status * * DESCRIPTION: Acpi_hw_obtain_sleep_type_register_data() obtains the SLP_TYP and *              SLP_TYPb values for the sleep state requested. * ******************************************************************************/acpi_statusacpi_hw_obtain_sleep_type_register_data (	u8                      sleep_state,	u8                      *slp_typ_a,	u8                      *slp_typ_b){	acpi_status             status = AE_OK;	acpi_operand_object     *obj_desc;	FUNCTION_TRACE ("Hw_obtain_sleep_type_register_data");	/*	 *  Validate parameters	 */	if ((sleep_state > ACPI_S_STATES_MAX) ||		!slp_typ_a || !slp_typ_b) {		return_ACPI_STATUS (AE_BAD_PARAMETER);	}	/*	 *  Acpi_evaluate the namespace object containing the values for this state	 */	status = acpi_ns_evaluate_by_name ((NATIVE_CHAR *) acpi_gbl_db_sleep_states[sleep_state],			  NULL, &obj_desc);	if (ACPI_FAILURE (status)) {		return_ACPI_STATUS (status);	}	if (!obj_desc) {		REPORT_ERROR (("Missing Sleep State object\n"));		return_ACPI_STATUS (AE_NOT_EXIST);	}	/*	 *  We got something, now ensure it is correct.  The object must	 *  be a package and must have at least 2 numeric values as the	 *  two elements	 */	/* Even though Acpi_evaluate_object resolves package references,	 * Ns_evaluate dpesn't. So, we do it here.	 */	status = acpi_ut_resolve_package_references(obj_desc);	if (obj_desc->package.count < 2) {		/* Must have at least two elements */		REPORT_ERROR (("Sleep State package does not have at least two elements\n"));		status = AE_ERROR;	}	else if (((obj_desc->package.elements[0])->common.type !=			 ACPI_TYPE_INTEGER) ||			 ((obj_desc->package.elements[1])->common.type !=				ACPI_TYPE_INTEGER)) {		/* Must have two  */		REPORT_ERROR (("Sleep State package elements are not both of type Number\n"));		status = AE_ERROR;	}	else {		/*		 *  Valid _Sx_ package size, type, and value		 */		*slp_typ_a = (u8) (obj_desc->package.elements[0])->integer.value;		*slp_typ_b = (u8) (obj_desc->package.elements[1])->integer.value;	}	if (ACPI_FAILURE (status)) {		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Bad Sleep object %p type %X\n",			obj_desc, obj_desc->common.type));	}	acpi_ut_remove_reference (obj_desc);	return_ACPI_STATUS (status);}/******************************************************************************* * * FUNCTION:    Acpi_hw_register_bit_access * * PARAMETERS:  Read_write      - Either ACPI_READ or ACPI_WRITE. *              Use_lock        - Lock the hardware *              Register_id     - index of ACPI Register to access *              Value           - (only used on write) value to write to the *                                Register.  Shifted all the way right. * * RETURN:      Value written to or read from specified Register.  This value *              is shifted all the way right. * * DESCRIPTION: Generic ACPI Register read/write function. * ******************************************************************************/u32acpi_hw_register_bit_access (	NATIVE_UINT             read_write,	u8                      use_lock,	u32                     register_id,	...)                    /* Value (only used on write) */{	u32                     register_value = 0;	u32                     mask = 0;	u32                     value = 0;	va_list                 marker;	FUNCTION_TRACE ("Hw_register_bit_access");	if (read_write == ACPI_WRITE) {		va_start (marker, register_id);		value = va_arg (marker, u32);		va_end (marker);	}	if (ACPI_MTX_LOCK == use_lock) {		acpi_ut_acquire_mutex (ACPI_MTX_HARDWARE);	}	/*	 * Decode the Register ID	 * Register id = Register block id | bit id	 *	 * Check bit id to fine locate Register offset.	 * Check Mask to determine Register offset, and then read-write.	 */	switch (REGISTER_BLOCK_ID (register_id)) {	case PM1_STS:		switch (register_id) {		case TMR_STS:			mask = TMR_STS_MASK;			break;		case BM_STS:			mask = BM_STS_MASK;			break;		case GBL_STS:			mask = GBL_STS_MASK;			break;		case PWRBTN_STS:			mask = PWRBTN_STS_MASK;			break;		case SLPBTN_STS:			mask = SLPBTN_STS_MASK;			break;		case RTC_STS:			mask = RTC_STS_MASK;			break;		case WAK_STS:			mask = WAK_STS_MASK;			break;		default:			mask = 0;			break;		}		register_value = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, PM1_STS);		if (read_write == ACPI_WRITE) {			/*			 * Status Registers are different from the rest.  Clear by			 * writing 1, writing 0 has no effect.  So, the only relevent			 * information is the single bit we're interested in, all			 * others should be written as 0 so they will be left			 * unchanged			 */			value <<= acpi_hw_get_bit_shift (mask);			value &= mask;			if (value) {				acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, PM1_STS,					(u16) value);				register_value = 0;			}		}		break;	case PM1_EN:		switch (register_id) {		case TMR_EN:			mask = TMR_EN_MASK;			break;		case GBL_EN:			mask = GBL_EN_MASK;			break;		case PWRBTN_EN:			mask = PWRBTN_EN_MASK;			break;		case SLPBTN_EN:			mask = SLPBTN_EN_MASK;			break;		case RTC_EN:			mask = RTC_EN_MASK;			break;		default:			mask = 0;			break;		}		register_value = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, PM1_EN);		if (read_write == ACPI_WRITE) {			register_value &= ~mask;			value          <<= acpi_hw_get_bit_shift (mask);			value          &= mask;			register_value |= value;			acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, PM1_EN, (u16) register_value);		}		break;	case PM1_CONTROL:		switch (register_id) {		case SCI_EN:			mask = SCI_EN_MASK;			break;		case BM_RLD:			mask = BM_RLD_MASK;			break;		case GBL_RLS:			mask = GBL_RLS_MASK;			break;		case SLP_TYPE_A:		case SLP_TYPE_B:			mask = SLP_TYPE_X_MASK;			break;		case SLP_EN:			mask = SLP_EN_MASK;			break;		default:			mask = 0;			break;		}		/*		 * Read the PM1 Control register.		 * Note that at this level, the fact that there are actually TWO		 * registers (A and B) and that B may not exist, are abstracted.		 */		register_value = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, PM1_CONTROL);		ACPI_DEBUG_PRINT ((ACPI_DB_IO, "PM1 control: Read %X\n", register_value));		if (read_write == ACPI_WRITE) {			register_value &= ~mask;			value          <<= acpi_hw_get_bit_shift (mask);			value          &= mask;			register_value |= value;			/*			 * SLP_TYPE_x Registers are written differently			 * than any other control Registers with			 * respect to A and B Registers.  The value			 * for A may be different than the value for B			 *			 * Therefore, pass the Register_id, not just generic PM1_CONTROL,			 * because we need to do different things. Yuck.			 */			acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, register_id,					(u16) register_value);		}		break;	case PM2_CONTROL:		switch (register_id) {		case ARB_DIS:			mask = ARB_DIS_MASK;			break;		default:			mask = 0;			break;		}		register_value = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, PM2_CONTROL);		ACPI_DEBUG_PRINT ((ACPI_DB_IO, "PM2 control: Read %X from %8.8X%8.8X\n",			register_value, HIDWORD(acpi_gbl_FADT->Xpm2_cnt_blk.address),			LODWORD(acpi_gbl_FADT->Xpm2_cnt_blk.address)));		if (read_write == ACPI_WRITE) {			register_value &= ~mask;			value          <<= acpi_hw_get_bit_shift (mask);			value          &= mask;			register_value |= value;			ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %04X to %8.8X%8.8X\n",				register_value,				HIDWORD(acpi_gbl_FADT->Xpm2_cnt_blk.address),				LODWORD(acpi_gbl_FADT->Xpm2_cnt_blk.address)));			acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK,					   PM2_CONTROL, (u8) (register_value));		}		break;	case PM_TIMER:		mask = TMR_VAL_MASK;		register_value = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK,				 PM_TIMER);		ACPI_DEBUG_PRINT ((ACPI_DB_IO, "PM_TIMER: Read %X from %8.8X%8.8X\n",			register_value,			HIDWORD(acpi_gbl_FADT->Xpm_tmr_blk.address),

⌨️ 快捷键说明

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