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

📄 prpower.c

📁 这个linux源代码是很全面的~基本完整了~使用c编译的~由于时间问题我没有亲自测试~但就算用来做参考资料也是非常好的
💻 C
📖 第 1 页 / 共 2 页
字号:
/***************************************************************************** * * Module Name: prpower.c *   $Revision: 32 $ * *****************************************************************************//* *  Copyright (C) 2000, 2001 Andrew Grover * *  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 *//* TBD: Linux specific */#include <linux/sched.h>#include <linux/pm.h>#include <asm/io.h>#include <acpi.h>#include <bm.h>#include "pr.h"#define _COMPONENT		ACPI_PROCESSOR	MODULE_NAME		("prpower")/**************************************************************************** *                                  Globals ****************************************************************************/extern FADT_DESCRIPTOR		acpi_fadt;static u32			last_idle_jiffies = 0;static PR_CONTEXT		*processor_list[NR_CPUS];static void			(*pr_pm_idle_save)(void) = NULL;static u8			bm_control = 0;/* Used for PIIX4 errata handling. */unsigned short			acpi_piix4_bmisx = 0;/**************************************************************************** *                             External Functions ****************************************************************************//**************************************************************************** * * FUNCTION:    pr_power_activate_state * * PARAMETERS: * * RETURN: * * DESCRIPTION: * ****************************************************************************/voidpr_power_activate_state (	PR_CONTEXT		*processor,	u32			next_state){	PROC_NAME("pr_power_activate_state");	if (!processor) {		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid (NULL) context.\n"));		return;	}	processor->power.state[processor->power.active_state].promotion.count = 0;	processor->power.state[processor->power.active_state].demotion.count = 0;	/*	 * Cleanup from old state.	 */	switch (processor->power.active_state) {	case PR_C3:		/* Disable bus master reload */		acpi_hw_register_bit_access(ACPI_WRITE, ACPI_MTX_DO_NOT_LOCK,			BM_RLD, 0);		break;	}	/*	 * Prepare to use new state.	 */	switch (next_state) {	case PR_C3:		/* Enable bus master reload */		acpi_hw_register_bit_access(ACPI_WRITE, ACPI_MTX_DO_NOT_LOCK,			BM_RLD, 1);		break;	}	processor->power.active_state = next_state;		return;}/**************************************************************************** * * FUNCTION:    pr_power_idle * * PARAMETERS:  <none> * * RETURN: * * DESCRIPTION: * ****************************************************************************/voidpr_power_idle (void){	PR_CX			*c_state = NULL;	u32			next_state = 0;	u32			start_ticks, end_ticks, time_elapsed;	PR_CONTEXT		*processor = NULL;	PROC_NAME("pr_power_idle");	processor = processor_list[smp_processor_id()];	if (!processor || processor->power.active_state == PR_C0) {		return;	}	next_state = processor->power.active_state;	/*	 * Check OS Idleness:	 * ------------------	 * If the OS has been busy (hasn't called the idle handler in a while)	 * then automatically demote to the default power state (e.g. C1).	 *	 * TBD: Optimize by having scheduler determine business instead	 *      of having us try to calculate it.	 */	if (processor->power.active_state != processor->power.default_state) {		if ((jiffies - last_idle_jiffies) >= processor->power.busy_metric) {			next_state = processor->power.default_state;			if (next_state != processor->power.active_state) {				pr_power_activate_state(processor, next_state);			}		}	}	disable();	/*	 * Log BM Activity:	 * ----------------	 * Read BM_STS and record its value for later use by C3 policy.	 * (Note that we save the BM_STS values for the last 32 cycles).	 */	if (bm_control) {		processor->power.bm_activity <<= 1;		if (acpi_hw_register_bit_access(ACPI_READ, ACPI_MTX_DO_NOT_LOCK, BM_STS)) {			processor->power.bm_activity |= 1;			acpi_hw_register_bit_access(ACPI_WRITE, ACPI_MTX_DO_NOT_LOCK,				BM_STS, 1);		}		else if (acpi_piix4_bmisx) {			/*			 * PIIX4 Errata:			 * -------------			 * This code is a workaround for errata #18 "C3 Power State/			 * BMIDE and Type-F DMA Livelock" from the July '01 PIIX4			 * specification update.  Note that BM_STS doesn't always			 * reflect the true state of bus mastering activity; forcing			 * us to manually check the BMIDEA bit of each IDE channel.			 */			if ((inb_p(acpi_piix4_bmisx + 0x02) & 0x01) ||				(inb_p(acpi_piix4_bmisx + 0x0A) & 0x01))				processor->power.bm_activity |= 1;		}	}	c_state = &(processor->power.state[processor->power.active_state]);	c_state->utilization++;	/*	 * Sleep:	 * ------	 * Invoke the current Cx state to put the processor to sleep.	 */	switch (processor->power.active_state) {	case PR_C1:		/* Invoke C1 */		enable(); halt();		/*	 * TBD: Can't get time duration while in C1, as resumes		 *      go to an ISR rather than here.		 */		time_elapsed = 0xFFFFFFFF;		break;	case PR_C2:		/* See how long we're asleep for */		acpi_get_timer(&start_ticks);		/* Invoke C2 */		acpi_os_read_port(processor->power.p_lvl2, NULL, 8);		/* Dummy op - must do something useless after P_LVL2 read */		acpi_hw_register_bit_access(ACPI_READ, ACPI_MTX_DO_NOT_LOCK, BM_STS);		/* Compute time elapsed */		acpi_get_timer(&end_ticks);		/* Re-enable interrupts */		enable();		acpi_get_timer_duration(start_ticks, end_ticks, &time_elapsed);		break;	case PR_C3:		/* Disable bus master arbitration */		acpi_hw_register_bit_access(ACPI_WRITE, ACPI_MTX_DO_NOT_LOCK, ARB_DIS, 1);		/* See how long we're asleep for */		acpi_get_timer(&start_ticks);		/* Invoke C3 */		acpi_os_read_port(processor->power.p_lvl3, NULL, 8);		/* Dummy op - must do something useless after P_LVL3 read */		acpi_hw_register_bit_access(ACPI_READ, ACPI_MTX_DO_NOT_LOCK, BM_STS);		/* Compute time elapsed */		acpi_get_timer(&end_ticks);		/* Enable bus master arbitration */		acpi_hw_register_bit_access(ACPI_WRITE, ACPI_MTX_DO_NOT_LOCK,			ARB_DIS, 0);		/* Re-enable interrupts */		enable();		acpi_get_timer_duration(start_ticks, end_ticks, &time_elapsed);		break;	default:		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Attempt to use unsupported power state C%d.\n", processor->power.active_state));		enable();		break;	}	/*	 * Promotion?	 * ----------	 * Track the number of successful sleeps (time asleep is greater	 * than time_threshold) and promote when count_threshold is	 * reached.	 */	if ((c_state->promotion.target_state) && 			(time_elapsed >= c_state->promotion.time_threshold)) {		c_state->promotion.count++; 		c_state->demotion.count = 0;		if (c_state->promotion.count >= c_state->promotion.count_threshold) {			/*			 * Bus Mastering Activity, if active and used			 * by this state's promotion policy, prevents			 * promotions from occuring.			 */			if (!bm_control || !(processor->power.bm_activity & c_state->promotion.bm_threshold))				next_state = c_state->promotion.target_state;		}	}	/*	 * Demotion?	 * ---------	 * Track the number of shorts (time asleep is less than	 * time_threshold) and demote when count_threshold is reached.	 */	if (c_state->demotion.target_state) {					if (time_elapsed < c_state->demotion.time_threshold) {			c_state->demotion.count++;			c_state->promotion.count = 0;			if (c_state->demotion.count >=				c_state->demotion.count_threshold) {				next_state = c_state->demotion.target_state;			}		}		/*		 * Bus Mastering Activity, if active and used by this		 * state's promotion policy, causes an immediate demotion		 * to occur.		 */		if (bm_control && (processor->power.bm_activity & c_state->demotion.bm_threshold))			next_state = c_state->demotion.target_state;	}	/*	 * New Cx State?	 * -------------	 * If we're going to start using a new Cx state we must clean up	 * from the previous and prepare to use the new.	 */	if (next_state != processor->power.active_state) {		pr_power_activate_state(processor, next_state);		processor->power.active_state = processor->power.active_state;	}	/*	 * Track OS Idleness:	 * ------------------	 * Record a jiffies timestamp to compute time elapsed between calls	 * to the idle handler.	 */	last_idle_jiffies = jiffies;	return;}/***************************************************************************** * * FUNCTION:    pr_power_set_default_policy

⌨️ 快捷键说明

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