Metropoli BBS
VIEWER: cpu_type.c MODE: TEXT (ASCII)
/*****************************************************************************
* Function:     cpu_type (char *dir0, char *dir1)
*
* Purpose:      Check for Cyrix CPU
*               Determination of which Cyrix CPU
*
* Technique:         Cyrix Identification Alogorithm:
*                   
*                       Execute 2 Tests:
*                         t1 = if CR2:2 is r/w  then t1 = TRUE else FALSE
*                         t2 = if CR3:7 is r/w  then t2 = TRUE else FALSE
*
*                       Decision Table:
*                          if  t1 and  t2 then DIR0 and DIR1 supported
*                          if  t1 and !t2 then Cx486S_a no ID Reg
*                          if !t1 and  t2 then Cx486SLC or DLC with DIR0,DIR1
*                          if !t1 and !t2 then Cx486_pr
*
* Parameters:  pointer to char dir0 value location
*              pointer to char dir1 value location  
*
* Returns:
*           unsigned short (16bit) <DIR1<15:8>,DIR0<7:0>               
*           DIR0 => Device Id             Value in Cyrix Register 0xfe 
*           DIR1 => Step Id and Revision  Value in Cyrix Register 0xff 
*
* Calls:        iscyrix()           - Test for Cyrix CPU 
*               cx_r (reg)          - Read Cyrix Configuration Register
*               cx_w (reg, val)     - Write Cyrix Configuration Register
*               isv86()             - Test if V86 mode
*               isb()               - Test for B step 
******************************************************************************/
#define UNKNOWN   0xff
#define Cx486_pr  0xfd  // ID Register not supported, software created
#define Cx486S_a  0xfe  // ID Register not supported, software created

#define FALSE     0
#define TRUE      1

#define CR2_MASK  0x4   // LockNW
#define CR3_MASK  0x80  // Resereved bit 7 

// Prototypes
int iscyrix();
char cx_r (char);
char cx_w (char, char);
int isv86();
int isb();

unsigned short cpu_type(char *dir0, char *dir1)
   {
   char temp, orgc2, newc2, orgc3, newc3;
   int cr2_rw=FALSE, cr3_rw=FALSE;
   unsigned short type;

   *dir0 = UNKNOWN;
   type = UNKNOWN;

   if ( iscyrix() )                     // this is a Cyrix part
      {
// ********* Disable SMI *********

      // ************************************
      // Test Cyrix c2 register read/writable
      // ************************************

      orgc2 = cx_r (0xc2);                // get current c2 value

      newc2 = orgc2 ^ CR2_MASK;           // toggle test bit
      cx_w (0xc2, newc2);                 // write test value to c2
      cx_r (0xc0);                        // dummy read to change bus

      if (cx_r (0xc2) != orgc2)       // did test bit toggle
         cr2_rw = TRUE;                // yes bit changed

      cx_w (0xc2, orgc2);        // return c2 to original value

      // ************************************
      // end c2 read writeable test
      // ************************************

      // ************************************
      // Test Cyrix c3 register read/writable
      // ************************************

      orgc3 = cx_r (0xc3);                // get current c3 value

      newc3 = orgc3 ^ CR3_MASK;           // toggle test bit
      cx_w (0xc3, newc3);                 // write test value to c3
      cx_r (0xc0);                        // dummy read to change bus

      if (cx_r (0xc3) != orgc3)          // did test bit change
         cr3_rw = TRUE;                   // yes it did

      cx_w (0xc3, orgc3);        // return c3 to original value

      // ************************************
      // end c3 read writeable test
      // ************************************

      if ((cr2_rw && cr3_rw) || (!cr2_rw && cr3_rw)) //DEV ID register ok
         {
         // <<<<<<< READ DEVICE ID Reg >>>>>>>>
         *dir0 = cx_r (0xfe);
         *dir1 = cx_r (0xff);

         type = *dir0;         // lower byte gets IDIR0
         type += *dir1 << 8;  // upper byte gets IDIR1
         }

      else if (cr2_rw && !cr3_rw)   // Cx486S A step
         {
         *dir0 = Cx486S_a;
         type = *dir0;              // lower byte
         }

      else if (!cr2_rw && !cr3_rw)  // Pre ID Regs. Cx486SLC or DLC
         {
         *dir0 = Cx486_pr;
         type = *dir0;           // lower byte

         if (!isv86 ())             // check v86 mode, can't do isb() in v86
            {
            *dir1 = isb()+1;        
            type += *dir1 << 12;    // upper byte, A step or early B
            }
         }

// ********* Enable SMI *********

      }  // Cyrix part


   return (type);
   }

[ RETURN TO DIRECTORY ]