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.

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