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.

350 lines
6.8 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. cyrix.c
  5. Abstract:
  6. Detects and initializes Cryix processors
  7. Author:
  8. Ken Reneris (kenr) 24-Feb-1994
  9. Environment:
  10. Kernel mode only.
  11. Revision History:
  12. --*/
  13. #include "ki.h"
  14. #define Cx486_SLC 0x0
  15. #define Cx486_DLC 0x1
  16. #define Cx486_SLC2 0x2
  17. #define Cx486_DLC2 0x3
  18. #define Cx486_SRx 0x4 // Retail Upgrade Cx486SLC
  19. #define Cx486_DRx 0x5 // Retail Upgrade Cx486DLC
  20. #define Cx486_SRx2 0x6 // Retail Upgrade 2x Cx486SLC
  21. #define Cx486_DRx2 0x7 // Retail Upgrade 2x Cx486DLC
  22. #define Cx486DX 0x1a
  23. #define Cx486DX2 0x1b
  24. #define M1 0x30
  25. #define CCR0 0xC0
  26. #define CCR1 0xC1
  27. #define CCR2 0xC2
  28. #define CCR3 0xC3
  29. #define DIR0 0xFE
  30. #define DIR1 0xFF
  31. // SRx & DRx flags
  32. #define CCR0_NC0 0x01 // No cache 64k @ 1M boundaries
  33. #define CCR0_NC1 0x02 // No cache 640k - 1M
  34. #define CCR0_A20M 0x04 // Enables A20M#
  35. #define CCR0_KEN 0x08 // Enables KEN#
  36. #define CCR0_FLUSH 0x10 // Enables FLUSH#
  37. // DX flags
  38. #define CCR1_NO_LOCK 0x10 // Ignore lock prefixes
  39. ULONG
  40. Ke386CyrixId (
  41. VOID
  42. );
  43. UCHAR
  44. ReadCyrixRegister (
  45. IN UCHAR Register
  46. );
  47. VOID
  48. WriteCyrixRegister (
  49. IN UCHAR Register,
  50. IN UCHAR Value
  51. );
  52. VOID
  53. Ke386ConfigureCyrixProcessor (
  54. VOID
  55. );
  56. #ifdef ALLOC_PRAGMA
  57. #pragma alloc_text(PAGE,Ke386CyrixId)
  58. #pragma alloc_text(PAGELK,Ke386ConfigureCyrixProcessor)
  59. #endif
  60. extern UCHAR CmpCyrixID[];
  61. ULONG
  62. Ke386CyrixId (
  63. VOID
  64. )
  65. /*++
  66. Routine Description:
  67. Detects and returns the Cyrix ID of the processor.
  68. This function only detects Cyrix processors which have internal
  69. cache support.
  70. Arguments:
  71. Configure - If TRUE, causes this function to alter
  72. the Cyrix CCR registers for the optimal NT
  73. performance.
  74. If FALSE, the processors configuration is
  75. not altered.
  76. Return Value:
  77. Cyrix ID of the processor
  78. 0 if not a Cyrix processor
  79. --*/
  80. {
  81. ULONG CyrixID;
  82. UCHAR r3, c;
  83. UCHAR flags;
  84. PKPRCB Prcb;
  85. CyrixID = 0;
  86. Prcb = KeGetCurrentPrcb();
  87. if (Prcb->CpuID && strcmp (Prcb->VendorString, CmpCyrixID)) {
  88. //
  89. // Not a Cyrix processor
  90. //
  91. return 0;
  92. }
  93. //
  94. // Test Div instruction to see if the flags
  95. // do not get altered
  96. //
  97. _asm {
  98. xor eax, eax
  99. sahf ; flags = ah
  100. lahf ; ah = flags
  101. mov flags, ah ; save flags
  102. mov eax, 5
  103. mov ecx, 2
  104. div cl ; 5 / 2 = ?
  105. lahf
  106. sub flags, ah ; flags = orig_flags - new_flags
  107. }
  108. if (flags == 0) {
  109. //
  110. // See if the Cyrix CCR3 register bit 0x80 can be editted.
  111. //
  112. r3 = ReadCyrixRegister(CCR3); // Read CCR3
  113. c = r3 ^ 0x80; // flip bit 80
  114. WriteCyrixRegister(CCR3, c); // Write CCR3
  115. ReadCyrixRegister(CCR0); // select new register
  116. c = ReadCyrixRegister(CCR3); // Read new CCR3 value
  117. if (ReadCyrixRegister(CCR3) != r3) {
  118. //
  119. // Read the Cyrix ID type register
  120. //
  121. CyrixID = ReadCyrixRegister(DIR0) + 1;
  122. }
  123. WriteCyrixRegister(CCR3, r3); // restore original CCR3 value
  124. }
  125. if (CyrixID > 0x7f) {
  126. // invalid setting
  127. CyrixID = 0;
  128. }
  129. return CyrixID;
  130. }
  131. static UCHAR
  132. ReadCyrixRegister (
  133. IN UCHAR Register
  134. )
  135. /*++
  136. Routine Description:
  137. Reads an internal Cyrix ID register. Note the internal register
  138. space is accessed via I/O addresses which are hooked internally
  139. to the processor.
  140. The caller is responsible for only calling this function on
  141. a Cyrix processor.
  142. Arguments:
  143. Register - Which Cyrix register to read
  144. Return Value:
  145. The registers value
  146. --*/
  147. {
  148. UCHAR Value;
  149. _asm {
  150. mov al, Register
  151. cli
  152. out 22h, al
  153. in al, 23h
  154. sti
  155. mov Value, al
  156. }
  157. return Value;
  158. }
  159. static VOID
  160. WriteCyrixRegister (
  161. IN UCHAR Register,
  162. IN UCHAR Value
  163. )
  164. /*++
  165. Routine Description:
  166. Write an internal Cyrix ID register. Note the internal register
  167. space is accessed via I/O addresses which are hooked internally
  168. to the processor.
  169. The caller is responsible for only calling this function on
  170. a Cyrix processor.
  171. Arguments:
  172. Register - Which Cyrix register to written
  173. Value - Value to write into the register
  174. Return Value:
  175. The registers value
  176. --*/
  177. {
  178. _asm {
  179. mov al, Register
  180. mov cl, Value
  181. cli
  182. out 22h, al
  183. mov al, cl
  184. out 23h, al
  185. sti
  186. }
  187. }
  188. VOID
  189. Ke386ConfigureCyrixProcessor (
  190. VOID
  191. )
  192. {
  193. UCHAR r0, r1;
  194. ULONG id, rev;
  195. PAGED_CODE();
  196. id = Ke386CyrixId();
  197. if (id) {
  198. ASSERT(ExPageLockHandle);
  199. MmLockPagableSectionByHandle(ExPageLockHandle);
  200. id = id - 1;
  201. rev = ReadCyrixRegister(DIR1);
  202. if ((id >= 0x20 && id <= 0x27) ||
  203. ((id & 0xF0) == M1 && rev < 0x17)) {
  204. //
  205. // These steppings have a write-back cache problem.
  206. // On these chips the L1 w/b cache can be disabled by
  207. // setting only the NW bit.
  208. //
  209. _asm {
  210. cli
  211. mov eax, cr0
  212. or eax, CR0_NW
  213. mov cr0, eax
  214. sti
  215. }
  216. }
  217. switch (id) {
  218. case Cx486_SRx:
  219. case Cx486_DRx:
  220. case Cx486_SRx2:
  221. case Cx486_DRx2:
  222. //
  223. // These processors have an internal cache feature
  224. // let's turn it on.
  225. //
  226. r0 = ReadCyrixRegister(CCR0);
  227. r0 |= CCR0_NC1 | CCR0_FLUSH;
  228. r0 &= ~CCR0_NC0;
  229. WriteCyrixRegister(CCR0, r0);
  230. // Clear Non-Cacheable Region 1
  231. WriteCyrixRegister(0xC4, 0);
  232. WriteCyrixRegister(0xC5, 0);
  233. WriteCyrixRegister(0xC6, 0);
  234. break;
  235. case Cx486DX:
  236. case Cx486DX2:
  237. //
  238. // Set NO_LOCK flag on these processors according to
  239. // the number of booted processors
  240. //
  241. r1 = ReadCyrixRegister(CCR1);
  242. r1 |= CCR1_NO_LOCK;
  243. if (KeNumberProcessors > 1) {
  244. r1 &= ~CCR1_NO_LOCK;
  245. }
  246. WriteCyrixRegister(CCR1, r1);
  247. break;
  248. }
  249. MmUnlockPagableImageSection (ExPageLockHandle);
  250. }
  251. }