📄 hwcpu32.c
字号:
/****************************************************************************** * * Name: hwcpu32.c - CPU support for IA32 (Throttling, Cx_states) * $Revision: 39 $ * *****************************************************************************//* * Copyright (C) 2000 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 "acnamesp.h"#include "achware.h"#define _COMPONENT HARDWARE MODULE_NAME ("Hwcpu32")#define BIT_4 0x10 /* TBD: [investigate] is this correct? *//**************************************************************************** * * FUNCTION: Acpi_hw_enter_c1 * * PARAMETERS: Pblk_address - Address of the processor control block * Pm_timer_ticks - Number of PM timer ticks elapsed while asleep * * RETURN: Function status. * * DESCRIPTION: Set C1 state on IA32 processor (halt) * ****************************************************************************/ACPI_STATUSacpi_hw_enter_c1( ACPI_IO_ADDRESS pblk_address, u32 *pm_timer_ticks){ u32 timer = 0; if (!pm_timer_ticks) { /* * Enter C1: * --------- */ enable(); halt(); *pm_timer_ticks = ACPI_UINT32_MAX; } else { timer = acpi_hw_pmt_ticks (); /* * Enter C1: * --------- */ enable (); halt (); /* * Compute Time in C1: * ------------------- */ timer = acpi_hw_pmt_ticks () - timer; *pm_timer_ticks = timer; } return (AE_OK);}/**************************************************************************** * * FUNCTION: Acpi_hw_enter_c2 * * PARAMETERS: Pblk_address - Address of the processor control block * Pm_timer_ticks - Number of PM timer ticks elapsed while asleep * * RETURN: <none> * * DESCRIPTION: Set C2 state on IA32 processor * ****************************************************************************/ACPI_STATUSacpi_hw_enter_c2( ACPI_IO_ADDRESS pblk_address, u32 *pm_timer_ticks){ u32 timer = 0; if (!pblk_address || !pm_timer_ticks) { return (AE_BAD_PARAMETER); } /* * Disable interrupts before all C2/C3 transitions. */ disable (); timer = acpi_hw_pmt_ticks (); /* * Enter C2: * --------- * Read from the P_LVL2 (P_BLK+4) register to invoke a C2 transition. */ acpi_os_in8 ((ACPI_IO_ADDRESS) (pblk_address + 4)); /* * Perform Dummy Op: * ----------------- * We have to do something useless after reading LVL2 because chipsets * cannot guarantee that STPCLK# gets asserted in time to freeze execution. */ acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, PM2_CONTROL); /* * Compute Time in C2: * ------------------- */ timer = acpi_hw_pmt_ticks () - timer; *pm_timer_ticks = timer; /* * Re-enable interrupts after coming out of C2/C3. */ enable (); return (AE_OK);}/**************************************************************************** * * FUNCTION: Acpi_hw_enter_c3 * * PARAMETERS: Pblk_address - Address of the processor control block * Pm_timer_ticks - Number of PM timer ticks elapsed while asleep * * RETURN: Status of function * * DESCRIPTION: Set C3 state on IA32 processor (UP only, cache coherency via * disabling bus mastering) * ****************************************************************************/ACPI_STATUSacpi_hw_enter_c3( ACPI_IO_ADDRESS pblk_address, u32 *pm_timer_ticks){ u32 timer = 0; u32 bus_master_status = 0; if (!pblk_address || !pm_timer_ticks) { return (AE_BAD_PARAMETER); } /* * Check the BM_STS bit, if it is set, do not enter C3 * but clear the bit (with a write) and exit, telling * the calling module that we spent zero time in C3. * If bus mastering continues, this action should * eventually cause a demotion to C2 */ if (1 == (bus_master_status = acpi_hw_register_bit_access (ACPI_READ, ACPI_MTX_LOCK, BM_STS))) { /* * Clear the BM_STS bit by setting it. */ acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_LOCK, BM_STS, 1); *pm_timer_ticks = 0; return (AE_OK); } /* * Disable interrupts before all C2/C3 transitions. */ disable(); /* * Disable Bus Mastering: * ---------------------- * Set the PM2_CNT.ARB_DIS bit (bit #0), preserving all other bits. */ acpi_hw_register_bit_access(ACPI_WRITE, ACPI_MTX_LOCK, ARB_DIS, 1); /* * Get the timer base before entering C state */ timer = acpi_hw_pmt_ticks (); /* * Enter C3: * --------- * Read from the P_LVL3 (P_BLK+5) register to invoke a C3 transition. */ acpi_os_in8 ((ACPI_IO_ADDRESS)(pblk_address + 5)); /* * Perform Dummy Op: * ----------------- * We have to do something useless after reading LVL3 because chipsets * cannot guarantee that STPCLK# gets asserted in time to freeze execution. */ acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, PM2_CONTROL); /* * Immediately compute the time in the C state */ timer = acpi_hw_pmt_ticks() - timer; /* * Re-Enable Bus Mastering: * ------------------------ * Clear the PM2_CNT.ARB_DIS bit (bit #0), preserving all other bits. */ acpi_hw_register_bit_access(ACPI_WRITE, ACPI_MTX_LOCK, ARB_DIS, 0); /* TBD: [Unhandled]: Support 24-bit timers (this algorithm assumes 32-bit) */ *pm_timer_ticks = timer; /* * Re-enable interrupts after coming out of C2/C3. */ enable(); return (AE_OK);}/**************************************************************************** * * FUNCTION: Acpi_hw_enter_cx * * PARAMETERS: Processor_handle - handle of the processor * * RETURN: Status of function * * DESCRIPTION: Invoke the currently active processor Cx handler to put this * processor to sleep. * ****************************************************************************/ACPI_STATUSacpi_hw_enter_cx ( ACPI_IO_ADDRESS pblk_address, u32 *pm_timer_ticks){ if (!acpi_hw_cx_handlers[acpi_hw_active_cx_state]) { return (AE_SUPPORT); } return (acpi_hw_cx_handlers[acpi_hw_active_cx_state] (pblk_address, pm_timer_ticks));}/**************************************************************************** * * FUNCTION: Acpi_hw_set_cx * * PARAMETERS: State - value (1-3) of the Cx state to 'make active' * * RETURN: Function status. * * DESCRIPTION: Sets the state to use during calls to Acpi_hw_enter_cx(). * ****************************************************************************/ACPI_STATUSacpi_hw_set_cx ( u32 cx_state){ /* * Supported State? * ---------------- */ if ((cx_state < 1) || (cx_state > 3)) { return (AE_BAD_PARAMETER); } if (!acpi_hw_cx_handlers[cx_state]) { return (AE_SUPPORT); } /* * New Cx State? * ------------- * We only care when moving from one state to another... */ if (acpi_hw_active_cx_state == cx_state) { return (AE_OK); } /* * Prepare to Use New State: * ------------------------- * If the new Cx_state is C3, the BM_RLD bit must be set to allow * the generation of a bus master requets to cause the processor * in the C3 state to transition to the C0 state. */ switch (cx_state) { case 3: acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_LOCK, BM_RLD, 1); break; } /* * Clean up from Old State: * ------------------------ * If the old Cx_state was C3, the BM_RLD bit is reset. When the * bit is reset, the generation of a bus master request does not * effect any processor in the C3 state. */ switch (acpi_hw_active_cx_state) { case 3: acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_LOCK, BM_RLD, 0); break; } /* * Enable: * ------- */ acpi_hw_active_cx_state = cx_state; return (AE_OK);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -