]> git.proxmox.com Git - mirror_edk2.git/blobdiff - OvmfPkg/Library/AcpiTimerLib/AcpiTimerLib.c
Add new API GetTimeInNanoSecond() to TimerLib to convert elapsed ticks to time in...
[mirror_edk2.git] / OvmfPkg / Library / AcpiTimerLib / AcpiTimerLib.c
old mode 100755 (executable)
new mode 100644 (file)
index 949a89d..a2f774f
@@ -1,8 +1,10 @@
 /** @file\r
   ACPI Timer implements one instance of Timer Library.\r
 \r
-  Copyright (c) 2008, Intel Corporation<BR> All rights\r
-  reserved. This program and the accompanying materials are\r
+  Copyright (c) 2008 - 2011, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2011, Andrei Warkentin <andreiw@motorola.com>\r
+\r
+  This program and the accompanying materials are\r
   licensed and made available under the terms and conditions of the BSD License\r
   which accompanies this distribution.  The full text of the license may be found at\r
   http://opensource.org/licenses/bsd-license.php\r
 #include <Library/BaseLib.h>\r
 #include <Library/IoLib.h>\r
 #include <Library/PciLib.h>\r
+#include <Library/DebugLib.h>\r
+\r
+//\r
+// PIIX4 Power Management Base Address\r
+//\r
+UINT32 mPmba = 0x400;\r
 \r
+#define PCI_BAR_IO             0x1\r
 #define ACPI_TIMER_FREQUENCY   3579545\r
 #define ACPI_TIMER_COUNT_SIZE  0x01000000\r
+#define ACPI_TIMER_OFFSET      0x8\r
 \r
 /**\r
   The constructor function enables ACPI IO space.\r
@@ -41,12 +51,21 @@ AcpiTimerLibConstructor (
   Device = 1;\r
   // Device = 7;\r
 \r
+  if (PciRead8 (PCI_LIB_ADDRESS (0,Device,3,0x80)) & 1) {\r
+    mPmba = PciRead32 (PCI_LIB_ADDRESS (0,Device,3,0x40));\r
+    ASSERT (mPmba & PCI_BAR_IO);\r
+    mPmba &= ~PCI_BAR_IO;\r
+  } else {\r
+    PciAndThenOr32 (PCI_LIB_ADDRESS (0,Device,3,0x40),\r
+                    (UINT32) ~0xfc0, mPmba);\r
+    PciOr8         (PCI_LIB_ADDRESS (0,Device,3,0x04), 0x01);\r
+  }\r
+\r
   //\r
   // ACPI Timer enable is in Bus 0, Device ?, Function 3\r
   //\r
-  PciOr8         (PCI_LIB_ADDRESS (0,Device,3,0x04), 0x01);\r
-  PciAndThenOr32 (PCI_LIB_ADDRESS (0,Device,3,0x40), (UINT32) ~0xfc0, 0x400);\r
-  PciOr8         (PCI_LIB_ADDRESS (0,Device,3,0x80), 0x01);  return RETURN_SUCCESS;\r
+  PciOr8         (PCI_LIB_ADDRESS (0,Device,3,0x80), 0x01);\r
+  return RETURN_SUCCESS;\r
 }\r
 \r
 /**\r
@@ -63,7 +82,7 @@ InternalAcpiGetTimerTick (
   VOID\r
   )\r
 {\r
-  return IoRead32 (0x408);\r
+  return IoRead32 (mPmba + ACPI_TIMER_OFFSET);\r
 }\r
 \r
 /**\r
@@ -220,3 +239,39 @@ GetPerformanceCounterProperties (
 \r
   return ACPI_TIMER_FREQUENCY;\r
 }\r
+\r
+/**\r
+  Converts elapsed ticks of performance counter to time in nanoseconds.\r
+\r
+  This function converts the elapsed ticks of running performance counter to\r
+  time value in unit of nanoseconds.\r
+\r
+  @param  Ticks     The number of elapsed ticks of running performance counter.\r
+\r
+  @return The elapsed time in nanoseconds.\r
+\r
+**/\r
+UINT64\r
+EFIAPI\r
+GetTimeInNanoSecond (\r
+  IN      UINT64                     Ticks\r
+  )\r
+{\r
+  UINT64  NanoSeconds;\r
+  UINT32  Remainder;\r
+\r
+  //\r
+  //          Ticks\r
+  // Time = --------- x 1,000,000,000\r
+  //        Frequency\r
+  //\r
+  NanoSeconds = MultU64x32 (DivU64x32Remainder (Ticks, ACPI_TIMER_FREQUENCY, &Remainder), 1000000000u);\r
+\r
+  //\r
+  // Frequency < 0x100000000, so Remainder < 0x100000000, then (Remainder * 1,000,000,000)\r
+  // will not overflow 64-bit.\r
+  //\r
+  NanoSeconds += DivU64x32 (MultU64x32 ((UINT64) Remainder, 1000000000u), ACPI_TIMER_FREQUENCY);\r
+\r
+  return NanoSeconds;\r
+}\r