Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

cyrix.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1989 Microsoft Corporation 00004 00005 Module Name: 00006 00007 cyrix.c 00008 00009 Abstract: 00010 00011 Detects and initializes Cryix processors 00012 00013 Author: 00014 00015 Ken Reneris (kenr) 24-Feb-1994 00016 00017 Environment: 00018 00019 Kernel mode only. 00020 00021 Revision History: 00022 00023 --*/ 00024 00025 #include "ki.h" 00026 00027 #define Cx486_SLC 0x0 00028 #define Cx486_DLC 0x1 00029 #define Cx486_SLC2 0x2 00030 #define Cx486_DLC2 0x3 00031 #define Cx486_SRx 0x4 // Retail Upgrade Cx486SLC 00032 #define Cx486_DRx 0x5 // Retail Upgrade Cx486DLC 00033 #define Cx486_SRx2 0x6 // Retail Upgrade 2x Cx486SLC 00034 #define Cx486_DRx2 0x7 // Retail Upgrade 2x Cx486DLC 00035 #define Cx486DX 0x1a 00036 #define Cx486DX2 0x1b 00037 #define M1 0x30 00038 00039 #define CCR0 0xC0 00040 #define CCR1 0xC1 00041 #define CCR2 0xC2 00042 #define CCR3 0xC3 00043 00044 #define DIR0 0xFE 00045 #define DIR1 0xFF 00046 00047 00048 // SRx & DRx flags 00049 #define CCR0_NC0 0x01 // No cache 64k @ 1M boundaries 00050 #define CCR0_NC1 0x02 // No cache 640k - 1M 00051 #define CCR0_A20M 0x04 // Enables A20M# 00052 #define CCR0_KEN 0x08 // Enables KEN# 00053 #define CCR0_FLUSH 0x10 // Enables FLUSH# 00054 00055 // DX flags 00056 #define CCR1_NO_LOCK 0x10 // Ignore lock prefixes 00057 00058 00059 ULONG 00060 Ke386CyrixId ( 00061 VOID 00062 ); 00063 00064 UCHAR 00065 ReadCyrixRegister ( 00066 IN UCHAR Register 00067 ); 00068 00069 VOID 00070 WriteCyrixRegister ( 00071 IN UCHAR Register, 00072 IN UCHAR Value 00073 ); 00074 00075 VOID 00076 Ke386ConfigureCyrixProcessor ( 00077 VOID 00078 ); 00079 00080 #ifdef ALLOC_PRAGMA 00081 #pragma alloc_text(PAGE,Ke386CyrixId) 00082 #pragma alloc_text(PAGELK,Ke386ConfigureCyrixProcessor) 00083 #endif 00084 00085 00086 extern UCHAR CmpCyrixID[]; 00087 00088 00089 00090 ULONG 00091 Ke386CyrixId ( 00092 VOID 00093 ) 00094 /*++ 00095 00096 Routine Description: 00097 00098 Detects and returns the Cyrix ID of the processor. 00099 This function only detects Cyrix processors which have internal 00100 cache support. 00101 00102 Arguments: 00103 00104 Configure - If TRUE, causes this function to alter 00105 the Cyrix CCR registers for the optimal NT 00106 performance. 00107 00108 If FALSE, the processors configuration is 00109 not altered. 00110 00111 00112 Return Value: 00113 00114 Cyrix ID of the processor 00115 0 if not a Cyrix processor 00116 00117 --*/ 00118 00119 { 00120 ULONG CyrixID; 00121 UCHAR r3, c; 00122 UCHAR flags; 00123 PKPRCB Prcb; 00124 00125 CyrixID = 0; 00126 00127 Prcb = KeGetCurrentPrcb(); 00128 if (Prcb->CpuID && strcmp (Prcb->VendorString, CmpCyrixID)) { 00129 00130 // 00131 // Not a Cyrix processor 00132 // 00133 00134 return 0; 00135 } 00136 00137 // 00138 // Test Div instruction to see if the flags 00139 // do not get altered 00140 // 00141 00142 _asm { 00143 xor eax, eax 00144 sahf ; flags = ah 00145 00146 lahf ; ah = flags 00147 mov flags, ah ; save flags 00148 00149 mov eax, 5 00150 mov ecx, 2 00151 div cl ; 5 / 2 = ? 00152 00153 lahf 00154 sub flags, ah ; flags = orig_flags - new_flags 00155 } 00156 00157 if (flags == 0) { 00158 00159 // 00160 // See if the Cyrix CCR3 register bit 0x80 can be editted. 00161 // 00162 00163 r3 = ReadCyrixRegister(CCR3); // Read CCR3 00164 c = r3 ^ 0x80; // flip bit 80 00165 WriteCyrixRegister(CCR3, c); // Write CCR3 00166 ReadCyrixRegister(CCR0); // select new register 00167 c = ReadCyrixRegister(CCR3); // Read new CCR3 value 00168 00169 if (ReadCyrixRegister(CCR3) != r3) { 00170 00171 // 00172 // Read the Cyrix ID type register 00173 // 00174 00175 CyrixID = ReadCyrixRegister(DIR0) + 1; 00176 } 00177 00178 WriteCyrixRegister(CCR3, r3); // restore original CCR3 value 00179 } 00180 00181 if (CyrixID > 0x7f) { 00182 // invalid setting 00183 CyrixID = 0; 00184 } 00185 00186 return CyrixID; 00187 } 00188 00189 static UCHAR 00190 ReadCyrixRegister ( 00191 IN UCHAR Register 00192 ) 00193 /*++ 00194 00195 Routine Description: 00196 00197 Reads an internal Cyrix ID register. Note the internal register 00198 space is accessed via I/O addresses which are hooked internally 00199 to the processor. 00200 00201 The caller is responsible for only calling this function on 00202 a Cyrix processor. 00203 00204 Arguments: 00205 00206 Register - Which Cyrix register to read 00207 00208 Return Value: 00209 00210 The registers value 00211 00212 --*/ 00213 00214 { 00215 UCHAR Value; 00216 00217 _asm { 00218 mov al, Register 00219 cli 00220 out 22h, al 00221 in al, 23h 00222 sti 00223 mov Value, al 00224 } 00225 return Value; 00226 } 00227 00228 00229 static VOID 00230 WriteCyrixRegister ( 00231 IN UCHAR Register, 00232 IN UCHAR Value 00233 ) 00234 /*++ 00235 00236 Routine Description: 00237 00238 Write an internal Cyrix ID register. Note the internal register 00239 space is accessed via I/O addresses which are hooked internally 00240 to the processor. 00241 00242 The caller is responsible for only calling this function on 00243 a Cyrix processor. 00244 00245 Arguments: 00246 00247 Register - Which Cyrix register to written 00248 Value - Value to write into the register 00249 00250 Return Value: 00251 00252 The registers value 00253 00254 --*/ 00255 00256 { 00257 _asm { 00258 mov al, Register 00259 mov cl, Value 00260 cli 00261 out 22h, al 00262 mov al, cl 00263 out 23h, al 00264 sti 00265 } 00266 } 00267 00268 00269 VOID 00270 Ke386ConfigureCyrixProcessor ( 00271 VOID 00272 ) 00273 { 00274 UCHAR r0, r1; 00275 ULONG id, rev; 00276 PVOID LockHandle; 00277 00278 00279 PAGED_CODE(); 00280 00281 id = Ke386CyrixId(); 00282 if (id) { 00283 00284 LockHandle = MmLockPagableCodeSection (&Ke386ConfigureCyrixProcessor); 00285 00286 id = id - 1; 00287 rev = ReadCyrixRegister(DIR1); 00288 00289 if ((id >= 0x20 && id <= 0x27) || 00290 ((id & 0xF0) == M1 && rev < 0x17)) { 00291 00292 // 00293 // These steppings have a write-back cache problem. 00294 // On these chips the L1 w/b cache can be disabled by 00295 // setting only the NW bit. 00296 // 00297 00298 _asm { 00299 cli 00300 00301 mov eax, cr0 00302 or eax, CR0_NW 00303 mov cr0, eax 00304 00305 sti 00306 } 00307 } 00308 00309 00310 switch (id) { 00311 case Cx486_SRx: 00312 case Cx486_DRx: 00313 case Cx486_SRx2: 00314 case Cx486_DRx2: 00315 00316 // 00317 // These processors have an internal cache feature 00318 // let's turn it on. 00319 // 00320 00321 r0 = ReadCyrixRegister(CCR0); 00322 r0 |= CCR0_NC1 | CCR0_FLUSH; 00323 r0 &= ~CCR0_NC0; 00324 WriteCyrixRegister(CCR0, r0); 00325 00326 // Clear Non-Cacheable Region 1 00327 WriteCyrixRegister(0xC4, 0); 00328 WriteCyrixRegister(0xC5, 0); 00329 WriteCyrixRegister(0xC6, 0); 00330 break; 00331 00332 case Cx486DX: 00333 case Cx486DX2: 00334 // 00335 // Set NO_LOCK flag on these processors according to 00336 // the number of booted processors 00337 // 00338 00339 r1 = ReadCyrixRegister(CCR1); 00340 r1 |= CCR1_NO_LOCK; 00341 if (KeNumberProcessors > 1) { 00342 r1 &= ~CCR1_NO_LOCK; 00343 } 00344 WriteCyrixRegister(CCR1, r1); 00345 break; 00346 } 00347 00348 MmUnlockPagableImageSection (LockHandle); 00349 } 00350 }

Generated on Sat May 15 19:39:38 2004 for test by doxygen 1.3.7