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.

354 lines
7.2 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. static
  44. UCHAR
  45. ReadCyrixRegister (
  46. IN UCHAR Register
  47. );
  48. static
  49. VOID
  50. WriteCyrixRegister (
  51. IN UCHAR Register,
  52. IN UCHAR Value
  53. );
  54. VOID
  55. Ke386ConfigureCyrixProcessor (
  56. VOID
  57. );
  58. #ifdef ALLOC_PRAGMA
  59. #pragma alloc_text(PAGE,Ke386CyrixId)
  60. #pragma alloc_text(PAGELK,Ke386ConfigureCyrixProcessor)
  61. #endif
  62. extern CHAR CmpCyrixID[];
  63. ULONG
  64. Ke386CyrixId (
  65. VOID
  66. )
  67. /*++
  68. Routine Description:
  69. Detects and returns the Cyrix ID of the processor.
  70. This function only detects Cyrix processors which have internal
  71. cache support.
  72. Arguments:
  73. Configure - If TRUE, causes this function to alter
  74. the Cyrix CCR registers for the optimal NT
  75. performance.
  76. If FALSE, the processors configuration is
  77. not altered.
  78. Return Value:
  79. Cyrix ID of the processor
  80. 0 if not a Cyrix processor
  81. --*/
  82. {
  83. ULONG CyrixID;
  84. UCHAR r3, c;
  85. UCHAR flags;
  86. PKPRCB Prcb;
  87. CyrixID = 0;
  88. Prcb = KeGetCurrentPrcb();
  89. if (Prcb->CpuID && strcmp ((PCHAR)Prcb->VendorString, CmpCyrixID)) {
  90. //
  91. // Not a Cyrix processor
  92. //
  93. return 0;
  94. }
  95. //
  96. // Test Div instruction to see if the flags
  97. // do not get altered
  98. //
  99. _asm {
  100. xor eax, eax
  101. sahf ; flags = ah
  102. lahf ; ah = flags
  103. mov flags, ah ; save flags
  104. mov eax, 5
  105. mov ecx, 2
  106. div cl ; 5 / 2 = ?
  107. lahf
  108. sub flags, ah ; flags = orig_flags - new_flags
  109. }
  110. if (flags == 0) {
  111. //
  112. // See if the Cyrix CCR3 register bit 0x80 can be editted.
  113. //
  114. r3 = ReadCyrixRegister(CCR3); // Read CCR3
  115. c = r3 ^ 0x80; // flip bit 80
  116. WriteCyrixRegister(CCR3, c); // Write CCR3
  117. ReadCyrixRegister(CCR0); // select new register
  118. c = ReadCyrixRegister(CCR3); // Read new CCR3 value
  119. if (ReadCyrixRegister(CCR3) != r3) {
  120. //
  121. // Read the Cyrix ID type register
  122. //
  123. CyrixID = ReadCyrixRegister(DIR0) + 1;
  124. }
  125. WriteCyrixRegister(CCR3, r3); // restore original CCR3 value
  126. }
  127. if (CyrixID > 0x7f) {
  128. // invalid setting
  129. CyrixID = 0;
  130. }
  131. return CyrixID;
  132. }
  133. static
  134. UCHAR
  135. ReadCyrixRegister (
  136. IN UCHAR Register
  137. )
  138. /*++
  139. Routine Description:
  140. Reads an internal Cyrix ID register. Note the internal register
  141. space is accessed via I/O addresses which are hooked internally
  142. to the processor.
  143. The caller is responsible for only calling this function on
  144. a Cyrix processor.
  145. Arguments:
  146. Register - Which Cyrix register to read
  147. Return Value:
  148. The registers value
  149. --*/
  150. {
  151. UCHAR Value;
  152. _asm {
  153. mov al, Register
  154. cli
  155. out 22h, al
  156. in al, 23h
  157. sti
  158. mov Value, al
  159. }
  160. return Value;
  161. }
  162. static
  163. VOID
  164. WriteCyrixRegister (
  165. IN UCHAR Register,
  166. IN UCHAR Value
  167. )
  168. /*++
  169. Routine Description:
  170. Write an internal Cyrix ID register. Note the internal register
  171. space is accessed via I/O addresses which are hooked internally
  172. to the processor.
  173. The caller is responsible for only calling this function on
  174. a Cyrix processor.
  175. Arguments:
  176. Register - Which Cyrix register to written
  177. Value - Value to write into the register
  178. Return Value:
  179. The register's value
  180. --*/
  181. {
  182. _asm {
  183. mov al, Register
  184. mov cl, Value
  185. cli
  186. out 22h, al
  187. mov al, cl
  188. out 23h, al
  189. sti
  190. }
  191. }
  192. VOID
  193. Ke386ConfigureCyrixProcessor (
  194. VOID
  195. )
  196. {
  197. UCHAR r0, r1;
  198. ULONG id, rev;
  199. PAGED_CODE();
  200. id = Ke386CyrixId();
  201. if (id) {
  202. ASSERT(ExPageLockHandle);
  203. MmLockPagableSectionByHandle(ExPageLockHandle);
  204. id = id - 1;
  205. rev = ReadCyrixRegister(DIR1);
  206. if ((id >= 0x20 && id <= 0x27) ||
  207. ((id & 0xF0) == M1 && rev < 0x17)) {
  208. //
  209. // These steppings have a write-back cache problem.
  210. // On these chips the L1 w/b cache can be disabled by
  211. // setting only the NW bit.
  212. //
  213. _asm {
  214. cli
  215. mov eax, cr0
  216. or eax, CR0_NW
  217. mov cr0, eax
  218. sti
  219. }
  220. }
  221. switch (id) {
  222. case Cx486_SRx:
  223. case Cx486_DRx:
  224. case Cx486_SRx2:
  225. case Cx486_DRx2:
  226. //
  227. // These processors have an internal cache feature
  228. // let's turn it on.
  229. //
  230. r0 = ReadCyrixRegister(CCR0);
  231. r0 |= CCR0_NC1 | CCR0_FLUSH;
  232. r0 &= ~CCR0_NC0;
  233. WriteCyrixRegister(CCR0, r0);
  234. // Clear Non-Cacheable Region 1
  235. WriteCyrixRegister(0xC4, 0);
  236. WriteCyrixRegister(0xC5, 0);
  237. WriteCyrixRegister(0xC6, 0);
  238. break;
  239. case Cx486DX:
  240. case Cx486DX2:
  241. //
  242. // Set NO_LOCK flag on these processors according to
  243. // the number of booted processors
  244. //
  245. r1 = ReadCyrixRegister(CCR1);
  246. r1 |= CCR1_NO_LOCK;
  247. if (KeNumberProcessors > 1) {
  248. r1 &= ~CCR1_NO_LOCK;
  249. }
  250. WriteCyrixRegister(CCR1, r1);
  251. break;
  252. }
  253. MmUnlockPagableImageSection (ExPageLockHandle);
  254. }
  255. }