test: cyrix.c Source File

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 }