Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

461 lines
10 KiB

  1. title "ACPI Timer Functions"
  2. ;++
  3. ;
  4. ; Copyright (c) 1989 Microsoft Corporation
  5. ;
  6. ; Module Name:
  7. ;
  8. ; pmtimer.asm
  9. ;
  10. ; Abstract:
  11. ;
  12. ; This module implements the code for ACPI-related timer
  13. ; functions.
  14. ;
  15. ; Author:
  16. ;
  17. ; Jake Oshins (jakeo) March 28, 1997
  18. ;
  19. ; Environment:
  20. ;
  21. ; Kernel mode only.
  22. ;
  23. ; Revision History:
  24. ;
  25. ; Split from pmclock.asm due to PIIX4 bugs.
  26. ;
  27. ;--
  28. .386p
  29. .xlist
  30. include hal386.inc
  31. include callconv.inc ; calling convention macros
  32. include mac386.inc
  33. include i386\ix8259.inc
  34. include i386\ixcmos.inc
  35. include xxacpi.h
  36. .list
  37. extrn _HalpFixedAcpiDescTable:DWORD
  38. extrn _HalpPiix4:byte
  39. extrn _HalpNextMSRate:DWORD
  40. extrn _PMTimerFreq:DWORD
  41. if DBG
  42. extrn _LastKQPCValue:DWORD
  43. endif
  44. ;
  45. ; ==== Values used for ACPI Clock ====
  46. ;
  47. _DATA SEGMENT DWORD PUBLIC 'DATA'
  48. MSBMASK24 equ 00800000h
  49. MSBMASK32 equ 80000000h
  50. CurrentTimePort equ 0
  51. TimeLow equ 4
  52. TimeHigh2 equ 8
  53. TimeHigh1 equ 12
  54. MsbMask equ 16
  55. BiasLow equ 20
  56. BiasHigh equ 24
  57. UpperBoundLow equ 28
  58. UpperBoundHigh2 equ 32
  59. UpperBoundHigh1 equ 36
  60. public _TimerInfo
  61. _TimerInfo dd 0,0,0,0,MSBMASK24,0,0,0,2,2
  62. public _QueryTimer
  63. _QueryTimer dd offset FLAT:@HalpQueryPerformanceCounter
  64. if 0
  65. ;
  66. ; The UpperBoundTable contains the values which should be added
  67. ; to the current counter value to ensure that the upper bound is
  68. ; reasonable. Values listed here are for all the 15 possible
  69. ; timer tick lengths. The unit is "PM Timer Ticks" and the
  70. ; value corresponds to the number of ticks that will pass in
  71. ; roughly two timer ticks at this rate.
  72. ;
  73. UpperBoundTable dd 14000 ; 1 ms
  74. dd 28600 ; 2 ms
  75. dd 43200 ; 3 ms
  76. dd 57200 ; 4 ms
  77. dd 71600 ; 5 ms
  78. dd 86000 ; 6 ms
  79. dd 100200 ; 7 ms
  80. dd 114600 ; 8 ms
  81. dd 128800 ; 9 ms
  82. dd 143400 ; 10 ms
  83. dd 157400 ; 11 ms
  84. dd 171800 ; 12 ms
  85. dd 186200 ; 13 ms
  86. dd 200400 ; 14 ms
  87. dd 214800 ; 15 ms
  88. endif
  89. if DBG
  90. TicksPassed dd 0,0
  91. public _TimerPerf, _TimerPerfIndex
  92. _TimerPerf db 4096 dup(0)
  93. RawRead0 equ 0
  94. RawRead1 equ 4
  95. AdjustedLow0 equ 8
  96. AdjustedHigh0 equ 12
  97. AdjustedLow1 equ 16
  98. AdjustedHigh1 equ 20
  99. TITL equ 24
  100. TITH equ 28
  101. UBL equ 32
  102. UBH equ 36
  103. ReturnedLow equ 40
  104. ReturnedHigh equ 44
  105. ReadCount equ 48
  106. TickMin equ 52
  107. TickCount equ 56
  108. TickNewUB equ 60
  109. TimerPerfBytes equ 64
  110. _TimerPerfIndex dd 0
  111. endif
  112. _DATA ends
  113. _TEXT$03 SEGMENT DWORD PUBLIC 'CODE'
  114. ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
  115. page ,132
  116. subttl "Query Performance Counter"
  117. ;++
  118. ;
  119. ; VOID
  120. ; HalCalibratePerformanceCounter (
  121. ; IN LONG volatile *Number,
  122. ; IN ULONGLONG NewCount
  123. ; )
  124. ;
  125. ; /*++
  126. ;
  127. ; Routine Description:
  128. ;
  129. ; This routine resets the performance counter value for the current
  130. ; processor to zero. The reset is done such that the resulting value
  131. ; is closely synchronized with other processors in the configuration.
  132. ;
  133. ; Arguments:
  134. ;
  135. ; Number - Supplies a pointer to count of the number of processors in
  136. ; the configuration.
  137. ;
  138. ; NewCount - Supplies the value to synchronize the counter too
  139. ;
  140. ; Return Value:
  141. ;
  142. ; None.
  143. ;--
  144. cPublicProc _HalpPmTimerCalibratePerfCount, 3
  145. cPublicFpo 3,1
  146. push edi
  147. mov edi, [esp+8] ; ponter to context
  148. cmp byte ptr PCR[PcNumber], 0 ; only execute on one processor
  149. jnz short hcp_50 ; if not boot processor, wait
  150. mov eax, _QueryTimer ; move current counter into edx:eax
  151. call eax
  152. mov ecx, [esp+12] ; compute how far current count
  153. sub ecx, eax ; is from target count
  154. mov eax, [esp+16]
  155. sbb eax, edx
  156. mov _TimerInfo.BiasLow, ecx ; replace bias
  157. mov _TimerInfo.BiasHigh, eax
  158. hcp_50:
  159. lock dec dword ptr [edi] ; count down
  160. @@: YIELD
  161. cmp dword ptr [edi], 0 ; wait for all processors to signal
  162. jnz short @b
  163. pop edi
  164. stdRET _HalpPmTimerCalibratePerfCount
  165. stdENDP _HalpPmTimerCalibratePerfCount
  166. page ,132
  167. subttl "Query Performance Counter"
  168. ;++
  169. ;
  170. ; LARGE_INTEGER
  171. ; FASTCALL
  172. ; HalpQueryPerformanceCounter(
  173. ; VOID
  174. ; )
  175. ;
  176. ; Routine Description:
  177. ;
  178. ; This function is a simplified form of HalpAcpiTimerQueryPerfCount
  179. ; meant to be used internally by the HAL.
  180. ;
  181. cPublicFastCall HalpQueryPerformanceCounter,0
  182. cPublicFpo 0, 2
  183. push ebx
  184. push esi
  185. ;
  186. ; Snap current times
  187. ;
  188. kqpc10: YIELD
  189. mov esi, _TimerInfo.TimeHigh2
  190. mov ebx, _TimerInfo.TimeLow
  191. cmp esi, _TimerInfo.TimeHigh1
  192. jne short kqpc10 ; Loop until consistent copy read
  193. mov edx, _TimerInfo.CurrentTimePort
  194. in eax, dx
  195. ;
  196. ; See if h/w MSb matches s/w copy
  197. ;
  198. mov ecx, _TimerInfo.MsbMask
  199. mov edx, eax
  200. xor edx, ebx
  201. and edx, ecx ; Isolate MSb match or mismatch
  202. ;
  203. ; Strip high hardware bit
  204. ;
  205. not ecx
  206. and eax, ecx
  207. not ecx
  208. ;
  209. ; merge low bits
  210. ;
  211. dec ecx
  212. not ecx
  213. and ebx, ecx
  214. or eax, ebx
  215. ;
  216. ; If there was a mismatch, add a tick
  217. ;
  218. add eax, edx
  219. adc esi, 0
  220. mov edx, esi ; get the top-half of the return value
  221. pop esi
  222. pop ebx
  223. fstRET HalpQueryPerformanceCounter
  224. fstENDP HalpQueryPerformanceCounter
  225. ;++
  226. ;
  227. ; LARGE_INTEGER
  228. ; HalpPmTimerQueryPerfCount (
  229. ; OUT PLARGE_INTEGER PerformanceFrequency OPTIONAL
  230. ; )
  231. ;
  232. ; Routine Description:
  233. ;
  234. ; This routine returns current 64-bit performance counter and,
  235. ; optionally, the Performance Frequency.
  236. ;
  237. ; N.B. The performace counter returned by this routine is
  238. ; not necessary the value when this routine is just entered.
  239. ; The value returned is actually the counter value at any point
  240. ; between the routine is entered and is exited.
  241. ;
  242. ; Arguments:
  243. ;
  244. ; PerformanceFrequency [TOS+4] - optionally, supplies the address
  245. ; of a variable to receive the performance counter frequency.
  246. ;
  247. ; Return Value:
  248. ;
  249. ; Current value of the performance counter will be returned.
  250. ;
  251. ;--
  252. KqpcFrequency EQU [esp+8] ; User supplied Performance Frequence
  253. cPublicProc _HalpPmTimerQueryPerfCount, 1
  254. .FPO (0, 1, 0, 1, 0, 0)
  255. push esi
  256. mov eax, _QueryTimer
  257. call eax
  258. if 0
  259. ;
  260. ; Check to see if the timer ever reports time moving backwards
  261. ;
  262. @@:
  263. mov esi, [_LastKQPCValue+8]
  264. mov ecx, [_LastKQPCValue]
  265. cmp esi, [_LastKQPCValue+4]
  266. jne short @b
  267. cmp edx, esi ; check for rollover
  268. jl short @f
  269. sub ecx, eax
  270. sbb esi, edx
  271. jng short @f
  272. int 3
  273. @@:
  274. mov [_LastKQPCValue+4], edx
  275. mov [_LastKQPCValue], eax
  276. mov [_LastKQPCValue+8], edx
  277. endif
  278. ;
  279. ; Apply bias to time
  280. ;
  281. mov ecx, _TimerInfo.BiasLow
  282. mov esi, _TimerInfo.BiasHigh
  283. add eax, ecx
  284. adc edx, esi
  285. mov ecx, KqpcFrequency
  286. or ecx, ecx
  287. jnz short kqpc20
  288. pop esi
  289. stdRET _HalpPmTimerQueryPerfCount
  290. kqpc20: mov esi, _PMTimerFreq
  291. mov [ecx], esi ; Hertz of PM timer
  292. mov [ecx+4], 0
  293. pop esi
  294. stdRET _HalpPmTimerQueryPerfCount
  295. stdENDP _HalpPmTimerQueryPerfCount
  296. ;++
  297. ;
  298. ; VOID
  299. ; HalAcpiTimerCarry (
  300. ; VOID
  301. ; )
  302. ;
  303. ; Routine Description:
  304. ;
  305. ; This routine is called to service the PM timer carry interrupt
  306. ;
  307. ; N.B. This function is called at interrupt time and assumes the
  308. ; caller clears the interrupt
  309. ;
  310. ; Arguments:
  311. ;
  312. ; None
  313. ;
  314. ; Return Value:
  315. ;
  316. ; None
  317. ;
  318. ;--
  319. cPublicProc _HalAcpiTimerCarry, 0
  320. cPublicFpo 0, 1
  321. push ebx
  322. ;
  323. ; Get current time from h/w
  324. ;
  325. mov edx, _TimerInfo.CurrentTimePort
  326. in eax, dx
  327. mov ebx, eax
  328. mov ecx, _TimerInfo.MsbMask
  329. mov eax, _TimerInfo.TimeLow
  330. mov edx, _TimerInfo.TimeHigh2
  331. ;
  332. ; Add one tick
  333. ;
  334. add eax, ecx
  335. adc edx, 0
  336. ;
  337. ; MSb of h/w should now match s/w. If not, add another tick
  338. ; to get them back in sync. (debugger might knock them
  339. ; out of sync)
  340. ;
  341. xor ebx, eax
  342. and ebx, ecx
  343. add eax, ebx
  344. adc edx, 0
  345. ;
  346. ; Store in reverse order of code which reads it
  347. ;
  348. mov _TimerInfo.TimeHigh1, edx
  349. mov _TimerInfo.TimeLow, eax
  350. mov _TimerInfo.TimeHigh2, edx
  351. pop ebx
  352. stdRET _HalAcpiTimerCarry
  353. stdENDP _HalAcpiTimerCarry
  354. ;++
  355. ;
  356. ; VOID
  357. ; HalAcpiBrokenPiix4TimerCarry (
  358. ; VOID
  359. ; )
  360. ;
  361. ; Routine Description:
  362. ;
  363. ; This routine does nothing. When we are using the Broken Piix4
  364. ; Code (TM), we are guaranteed to have examined the timer many times
  365. ; since the last rollover. So we don't need to do any bookkeeping
  366. ; here.
  367. ;
  368. ; N.B. This function is called at interrupt time and assumes the
  369. ; caller clears the interrupt
  370. ;
  371. ; Arguments:
  372. ;
  373. ; None
  374. ;
  375. ; Return Value:
  376. ;
  377. ; None
  378. ;
  379. ;--
  380. cPublicProc _HalAcpiBrokenPiix4TimerCarry, 0
  381. stdRET _HalAcpiBrokenPiix4TimerCarry
  382. stdENDP _HalAcpiBrokenPiix4TimerCarry
  383. _TEXT$03 ends
  384. end