hwtimer.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:6k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /******************************************************************************
  2.  *
  3.  * Name: hwtimer.c - ACPI Power Management Timer Interface
  4.  *              $Revision: 14 $
  5.  *
  6.  *****************************************************************************/
  7. /*
  8.  *  Copyright (C) 2000, 2001 R. Byron Moore
  9.  *
  10.  *  This program is free software; you can redistribute it and/or modify
  11.  *  it under the terms of the GNU General Public License as published by
  12.  *  the Free Software Foundation; either version 2 of the License, or
  13.  *  (at your option) any later version.
  14.  *
  15.  *  This program is distributed in the hope that it will be useful,
  16.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  *  GNU General Public License for more details.
  19.  *
  20.  *  You should have received a copy of the GNU General Public License
  21.  *  along with this program; if not, write to the Free Software
  22.  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  23.  */
  24. #include "acpi.h"
  25. #include "achware.h"
  26. #define _COMPONENT          ACPI_HARDWARE
  27.  MODULE_NAME         ("hwtimer")
  28. /******************************************************************************
  29.  *
  30.  * FUNCTION:    Acpi_get_timer_resolution
  31.  *
  32.  * PARAMETERS:  none
  33.  *
  34.  * RETURN:      Number of bits of resolution in the PM Timer (24 or 32).
  35.  *
  36.  * DESCRIPTION: Obtains resolution of the ACPI PM Timer.
  37.  *
  38.  ******************************************************************************/
  39. acpi_status
  40. acpi_get_timer_resolution (
  41. u32                     *resolution)
  42. {
  43. FUNCTION_TRACE ("Acpi_get_timer_resolution");
  44. if (!resolution) {
  45. return_ACPI_STATUS (AE_BAD_PARAMETER);
  46. }
  47. if (0 == acpi_gbl_FADT->tmr_val_ext) {
  48. *resolution = 24;
  49. }
  50. else {
  51. *resolution = 32;
  52. }
  53. return_ACPI_STATUS (AE_OK);
  54. }
  55. /******************************************************************************
  56.  *
  57.  * FUNCTION:    Acpi_get_timer
  58.  *
  59.  * PARAMETERS:  none
  60.  *
  61.  * RETURN:      Current value of the ACPI PM Timer (in ticks).
  62.  *
  63.  * DESCRIPTION: Obtains current value of ACPI PM Timer.
  64.  *
  65.  ******************************************************************************/
  66. acpi_status
  67. acpi_get_timer (
  68. u32                     *ticks)
  69. {
  70. FUNCTION_TRACE ("Acpi_get_timer");
  71. if (!ticks) {
  72. return_ACPI_STATUS (AE_BAD_PARAMETER);
  73. }
  74. acpi_os_read_port ((ACPI_IO_ADDRESS)
  75. ACPI_GET_ADDRESS (acpi_gbl_FADT->Xpm_tmr_blk.address), ticks, 32);
  76. return_ACPI_STATUS (AE_OK);
  77. }
  78. /******************************************************************************
  79.  *
  80.  * FUNCTION:    Acpi_get_timer_duration
  81.  *
  82.  * PARAMETERS:  Start_ticks
  83.  *              End_ticks
  84.  *              Time_elapsed
  85.  *
  86.  * RETURN:      Time_elapsed
  87.  *
  88.  * DESCRIPTION: Computes the time elapsed (in microseconds) between two
  89.  *              PM Timer time stamps, taking into account the possibility of
  90.  *              rollovers, the timer resolution, and timer frequency.
  91.  *
  92.  *              The PM Timer's clock ticks at roughly 3.6 times per
  93.  *              _microsecond_, and its clock continues through Cx state
  94.  *              transitions (unlike many CPU timestamp counters) -- making it
  95.  *              a versatile and accurate timer.
  96.  *
  97.  *              Note that this function accomodates only a single timer
  98.  *              rollover.  Thus for 24-bit timers, this function should only
  99.  *              be used for calculating durations less than ~4.6 seconds
  100.  *              (~20 hours for 32-bit timers).
  101.  *
  102.  ******************************************************************************/
  103. acpi_status
  104. acpi_get_timer_duration (
  105. u32                     start_ticks,
  106. u32                     end_ticks,
  107. u32                     *time_elapsed)
  108. {
  109. u32                     delta_ticks = 0;
  110. u32                     seconds = 0;
  111. u32                     milliseconds = 0;
  112. u32                     microseconds = 0;
  113. u32                     remainder = 0;
  114. FUNCTION_TRACE ("Acpi_get_timer_duration");
  115. if (!time_elapsed) {
  116. return_ACPI_STATUS (AE_BAD_PARAMETER);
  117. }
  118. /*
  119.  * Compute Tick Delta:
  120.  * -------------------
  121.  * Handle (max one) timer rollovers on 24- versus 32-bit timers.
  122.  */
  123. if (start_ticks < end_ticks) {
  124. delta_ticks = end_ticks - start_ticks;
  125. }
  126. else if (start_ticks > end_ticks) {
  127. /* 24-bit Timer */
  128. if (0 == acpi_gbl_FADT->tmr_val_ext) {
  129. delta_ticks = (((0x00FFFFFF - start_ticks) + end_ticks) & 0x00FFFFFF);
  130. }
  131. /* 32-bit Timer */
  132. else {
  133. delta_ticks = (0xFFFFFFFF - start_ticks) + end_ticks;
  134. }
  135. }
  136. else {
  137. *time_elapsed = 0;
  138. return_ACPI_STATUS (AE_OK);
  139. }
  140. /*
  141.  * Compute Duration:
  142.  * -----------------
  143.  * Since certain compilers (gcc/Linux, argh!) don't support 64-bit
  144.  * divides in kernel-space we have to do some trickery to preserve
  145.  * accuracy while using 32-bit math.
  146.  *
  147.  * TBD: Change to use 64-bit math when supported.
  148.  *
  149.  * The process is as follows:
  150.  *  1. Compute the number of seconds by dividing Delta Ticks by
  151.  *     the timer frequency.
  152.  *  2. Compute the number of milliseconds in the remainder from step #1
  153.  *     by multiplying by 1000 and then dividing by the timer frequency.
  154.  *  3. Compute the number of microseconds in the remainder from step #2
  155.  *     by multiplying by 1000 and then dividing by the timer frequency.
  156.  *  4. Add the results from steps 1, 2, and 3 to get the total duration.
  157.  *
  158.  * Example: The time elapsed for Delta_ticks = 0xFFFFFFFF should be
  159.  *          1199864031 microseconds.  This is computed as follows:
  160.  *          Step #1: Seconds = 1199; Remainder = 3092840
  161.  *          Step #2: Milliseconds = 864; Remainder = 113120
  162.  *          Step #3: Microseconds = 31; Remainder = <don't care!>
  163.  */
  164. /* Step #1 */
  165. seconds = delta_ticks / PM_TIMER_FREQUENCY;
  166. remainder = delta_ticks % PM_TIMER_FREQUENCY;
  167. /* Step #2 */
  168. milliseconds = (remainder * 1000) / PM_TIMER_FREQUENCY;
  169. remainder = (remainder * 1000) % PM_TIMER_FREQUENCY;
  170. /* Step #3 */
  171. microseconds = (remainder * 1000) / PM_TIMER_FREQUENCY;
  172. /* Step #4 */
  173. *time_elapsed = seconds * 1000000;
  174. *time_elapsed += milliseconds * 1000;
  175. *time_elapsed += microseconds;
  176. return_ACPI_STATUS (AE_OK);
  177. }