+\r
+/**\r
+ Calculate TSC frequency.\r
+\r
+ The TSC counting frequency is determined by comparing how far it counts\r
+ during a 101.4 us period as determined by the ACPI timer.\r
+ The ACPI timer is used because it counts at a known frequency.\r
+ The TSC is sampled, followed by waiting 363 counts of the ACPI timer,\r
+ or 101.4 us. The TSC is then sampled again. The difference multiplied by\r
+ 9861 is the TSC frequency. There will be a small error because of the\r
+ overhead of reading the ACPI timer. An attempt is made to determine and\r
+ compensate for this error.\r
+\r
+ @return The number of TSC counts per second.\r
+\r
+**/\r
+UINT64\r
+InternalCalculateTscFrequency (\r
+ VOID\r
+ )\r
+{\r
+ UINT64 StartTSC;\r
+ UINT64 EndTSC;\r
+ UINT16 TimerAddr;\r
+ UINT32 Ticks;\r
+ UINT64 TscFrequency;\r
+ BOOLEAN InterruptState;\r
+\r
+ InterruptState = SaveAndDisableInterrupts ();\r
+\r
+ TimerAddr = InternalAcpiGetAcpiTimerIoPort ();\r
+ //\r
+ // Compute the number of ticks to wait to measure TSC frequency.\r
+ // Use 363 * 9861 = 3579543 Hz which is within 2 Hz of ACPI_TIMER_FREQUENCY.\r
+ // 363 counts is a calibration time of 101.4 uS.\r
+ //\r
+ Ticks = IoBitFieldRead32 (TimerAddr, 0, 23) + 363;\r
+\r
+ StartTSC = AsmReadTsc (); // Get base value for the TSC\r
+ //\r
+ // Wait until the ACPI timer has counted 101.4 us.\r
+ // Timer wrap-arounds are handled correctly by this function.\r
+ // When the current ACPI timer value is greater than 'Ticks',\r
+ // the while loop will exit.\r
+ //\r
+ while (((Ticks - IoBitFieldRead32 (TimerAddr, 0, 23)) & BIT23) == 0) {\r
+ CpuPause();\r
+ }\r
+ EndTSC = AsmReadTsc (); // TSC value 101.4 us later\r
+\r
+ TscFrequency = MultU64x32 (\r
+ (EndTSC - StartTSC), // Number of TSC counts in 101.4 us\r
+ 9861 // Number of 101.4 us in a second\r
+ );\r
+\r
+ SetInterruptState (InterruptState);\r
+\r
+ return TscFrequency;\r
+}\r
+\r