Leaked source code of windows server 2003
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.

363 lines
9.5 KiB

  1. SETUP equ 1
  2. ;**
  3. ;
  4. ; Machine-specific detection code
  5. ;
  6. ;--
  7. .386p
  8. include hal386.inc
  9. include callconv.inc
  10. _TEXT SEGMENT DWORD PUBLIC 'CODE'
  11. ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
  12. ;
  13. ; Thunk functions.
  14. ; Equivalent Hal functions which various detection code may use
  15. ;
  16. ;++
  17. ;
  18. ; CMOS space read functions.
  19. ;
  20. ;--
  21. CMOSAddressPort equ 70H
  22. CMOSDataPort equ 71H
  23. CMOSExAddressLSBPort equ 74H
  24. CMOSExAddressMSBPort equ 75H
  25. CMOSExDataPort equ 76H
  26. ;++
  27. ;
  28. ; VOID
  29. ; ReadCMOS(
  30. ; ULONG StartingOffset
  31. ; ULONG Count
  32. ; PUCHAR ReturnValuePtr
  33. ; )
  34. ;
  35. ; Read CMOS starting at the given offset for the given number of
  36. ; bytes putting the bytes read into the buffer pointed to by the
  37. ; given address.
  38. ;
  39. ; Arguments:
  40. ;
  41. ; StartingOffset : where to start in CMOS
  42. ;
  43. ; Count : how many bytes to read
  44. ;
  45. ; ReturnValuePtr : where to put bytes read
  46. ;
  47. ; Returns:
  48. ; None.
  49. ;
  50. ;--
  51. StartingOffset equ 2*4[ebp]
  52. Count equ 3*4[ebp]
  53. ReturnValuePtr equ 4*4[ebp]
  54. cPublicProc _ReadCMOS,3
  55. push ebp
  56. mov ebp, esp
  57. push ebx ; caller's reg
  58. push edi ; caller's reg
  59. mov ebx, StartingOffset
  60. mov ecx, Count
  61. mov edi, ReturnValuePtr
  62. align dword
  63. NextByte:
  64. cmp bh, 0
  65. jne ExCMOSRead
  66. mov al, bl
  67. out CMOSAddressPort, al
  68. in al, CMOSDataPort
  69. mov [edi], al
  70. add ebx, 1
  71. add edi, 1
  72. sub ecx, 1
  73. jg NextByte
  74. pop edi ; restore caller's reg
  75. pop ebx ; restore caller's reg
  76. pop ebp
  77. stdRET _ReadCmos
  78. align dword
  79. ExCMOSRead:
  80. mov al, bl
  81. out CMOSExAddressLSBPort, al
  82. mov al, bh
  83. out CMOSExAddressMSBPort, al
  84. in al, CMOSExDataPort
  85. mov [edi], al
  86. add ebx, 1
  87. add edi, 1
  88. sub ecx, 1
  89. jg ExCMOSRead
  90. pop edi ; restore caller's reg
  91. pop ebx ; restore caller's reg
  92. pop ebp
  93. stdRET _ReadCMOS
  94. stdENDP _ReadCMOS
  95. ; 486 C step CPU detection code.
  96. CR0_ET equ 10h
  97. CR0_TS equ 08H
  98. CR0_EM equ 04H
  99. CR0_MP equ 02H
  100. ;
  101. ; The following equates define the control bits of EFALGS register
  102. ;
  103. EFLAGS_AC equ 40000h
  104. EFLAGS_ID equ 200000h
  105. ;
  106. ; Constants for Floating Point test
  107. ;
  108. REALLONG_LOW equ 00000000
  109. REALLONG_HIGH equ 3FE00000h
  110. PSEUDO_DENORMAL_LOW equ 00000000h
  111. PSEUDO_DENORMAL_MID equ 80000000h
  112. PSEUDO_DENORMAL_HIGH equ 0000h
  113. ;
  114. ; Define the iret frame
  115. ;
  116. IretFrame struc
  117. IretEip dd 0
  118. IretCs dd 0
  119. IretEFlags dd 0
  120. IretFrame ends
  121. ;++
  122. ;
  123. ; BOOLEAN
  124. ; Detect486CStep (
  125. ; IN PBOOLEAN Dummy
  126. ; )
  127. ;
  128. ; Routine Description:
  129. ;
  130. ; Returns TRUE if the processor is a 486 C stepping. We detect the CPU
  131. ; in order to use a specific HAL. This HAL attempts to work around
  132. ; a 486 C stepping bug which the normal HAL tends to aggravate.
  133. ;
  134. cPublicProc _Detect486CStep,1
  135. push edi
  136. push esi
  137. push ebx ; Save C registers
  138. mov eax, cr0
  139. push eax
  140. pushfd ; save Cr0 & flags
  141. pop ebx ; Get flags into eax
  142. push ebx ; Save original flags
  143. mov ecx, ebx
  144. xor ecx, EFLAGS_AC ; flip AC bit
  145. push ecx
  146. popfd ; load it into flags
  147. pushfd ; re-save flags
  148. pop ecx ; get flags into eax
  149. cmp ebx, ecx ; did bit stay flipped?
  150. je short Not486C ; No, then this is a 386
  151. mov ecx, ebx
  152. xor ecx, EFLAGS_ID ; flip ID bit
  153. push ecx
  154. popfd ; load it into flags
  155. pushfd ; re-save flags
  156. pop ecx ; get flags into eax
  157. cmp ebx, ecx ; did bit stay flipped?
  158. jne short Not486C ; Yes, then this >= 586
  159. mov eax, cr0
  160. and eax, NOT (CR0_ET+CR0_MP+CR0_TS+CR0_EM)
  161. mov cr0, eax
  162. call IsNpxPresent ; Check if cpu has coprocessor support?
  163. or ax, ax
  164. jz short Is486C ; it is actually 486sx, assume C step
  165. call Check486CStepping ; Check for <= C stepping
  166. jnc short Not486C ; if nc, it is NOT a C stepping
  167. Is486C:
  168. mov eax, 1 ; Return TRUE
  169. jmp short DetectCpuExit
  170. Not486C:
  171. xor eax, eax
  172. DetectCpuExit:
  173. popfd
  174. pop ebx
  175. mov cr0, ebx
  176. pop ebx
  177. pop esi
  178. pop edi
  179. stdRET _Detect486CStep
  180. stdENDP _Detect486CStep
  181. ;++
  182. ;
  183. ; BOOLEAN
  184. ; Check486CStepping (
  185. ; VOID
  186. ; )
  187. ;
  188. ; Routine Description:
  189. ;
  190. ; This routine checks for 486 C Stepping.
  191. ;
  192. ; This routine takes advantage of the fact that FSCALE produces
  193. ; wrong result with Denormal or Pseudo-denormal operand on 486
  194. ; C and earlier steps.
  195. ;
  196. ; If the value contained in ST(1), second location in the floating
  197. ; point stack, is between 1 and 11, and the value in ST, top of the
  198. ; floating point stack, is either a pseudo-denormal number or a
  199. ; denormal number with the underflow exception unmasked, the FSCALE
  200. ; instruction produces an incorrect result.
  201. ;
  202. ; Arguments:
  203. ;
  204. ; None.
  205. ;
  206. ; Return Value:
  207. ;
  208. ; Carry Flag clear if D or later stepping.
  209. ; Carry Flag set if C stepping.
  210. ;
  211. ;--
  212. FpControl equ [ebp - 2]
  213. RealLongSt1 equ [ebp - 10]
  214. PseudoDenormal equ [ebp - 20]
  215. FscaleResult equ [ebp - 30]
  216. public Check486CStepping
  217. Check486CStepping proc
  218. push ebp
  219. mov ebp, esp
  220. sub esp, 30 ; Allocate space for temp real variables
  221. ;
  222. ; Initialize the local FP variables to predefined values.
  223. ; RealLongSt1 = 1.0 * (2 ** -1) = 0.5 in normalized double precision FP form
  224. ; PseudoDenormal = a unsupported format by IEEE.
  225. ; Sign bit = 0
  226. ; Exponent = 000000000000000B
  227. ; Significand = 100000...0B
  228. ; FscaleResult = The result of FSCALE instruction. Depending on 486 step,
  229. ; the value will be different:
  230. ; Under C and earlier steps, 486 returns the original value
  231. ; in ST as the result. The correct returned value should be
  232. ; original significand and an exponent of 0...01.
  233. ;
  234. mov dword ptr RealLongSt1, REALLONG_LOW
  235. mov dword ptr RealLongSt1 + 4, REALLONG_HIGH
  236. mov dword ptr PseudoDenormal, PSEUDO_DENORMAL_LOW
  237. mov dword ptr PseudoDenormal + 4, PSEUDO_DENORMAL_MID
  238. mov word ptr PseudoDenormal + 8, PSEUDO_DENORMAL_HIGH
  239. .387
  240. fnstcw FpControl ; Get FP control word
  241. or word ptr FpControl, 0FFh ; Mask all the FP exceptions
  242. fldcw FpControl ; Set FP control
  243. fld qword ptr RealLongSt1 ; 0 < ST(1) = RealLongSt1 < 1
  244. fld tbyte ptr PseudoDenormal; Denormalized operand. Note, i486
  245. ; won't report denormal exception
  246. ; on 'FLD' instruction.
  247. ; ST(0) = Extended Denormalized operand
  248. fscale ; try to trigger 486Cx errata
  249. fstp tbyte ptr FscaleResult ; Store ST(0) in FscaleResult
  250. cmp word ptr FscaleResult + 8, PSEUDO_DENORMAL_HIGH
  251. ; Is Exponent changed?
  252. jz short c4ds00 ; if z, no, it is C step
  253. clc
  254. jmp short c4ds10
  255. c4ds00: stc
  256. c4ds10: mov esp, ebp
  257. pop ebp
  258. ret
  259. Check486CStepping endp
  260. ;++
  261. ;
  262. ; BOOLEAN
  263. ; IsNpxPresent(
  264. ; VOID
  265. ; );
  266. ;
  267. ; Routine Description:
  268. ;
  269. ; This routine determines if there is any Numeric coprocessor
  270. ; present.
  271. ;
  272. ; Arguments:
  273. ;
  274. ; None.
  275. ;
  276. ; Return:
  277. ;
  278. ; TRUE - If NPX is present. Else a value of FALSE is returned.
  279. ;
  280. ;--
  281. public IsNpxPresent
  282. IsNpxPresent proc near
  283. push ebp ; Save caller's bp
  284. xor edx, edx
  285. .287
  286. fninit ; Initialize NPX
  287. mov ecx, 5A5A5A5Ah ; Put non-zero value
  288. push ecx ; into the memory we are going to use
  289. mov ebp, esp
  290. fnstsw word ptr [ebp] ; Retrieve status - must use non-wait
  291. cmp byte ptr [ebp], 0 ; All bits cleared by fninit?
  292. jne Inp10
  293. mov edx, 1
  294. Inp10:
  295. pop eax ; clear scratch value
  296. pop ebp ; Restore caller's bp
  297. mov eax, edx
  298. ret
  299. IsNpxPresent endp
  300. _TEXT ENDS
  301. END