home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 8 Other / 08-Other.zip / set6x86.zip / 6x86_reg.c next >
C/C++ Source or Header  |  1998-01-03  |  11KB  |  346 lines

  1. /*  6x86_reg: a tool for displaying Cyrix 6x86 configuration registers
  2.  *  and ARRs in human-readable format.
  3.  *
  4.  *  Copyright (C) 1996, 1997  Koen Gadeyne
  5.  *  Modifications for OS/2 port by Greg Kondrasuk, 1998.
  6.  *
  7.  *  This program is free software; you can redistribute it and/or modify
  8.  *  it under the terms of the GNU General Public License as published by
  9.  *  the Free Software Foundation; either version 2 of the License, or
  10.  *  (at your option) any later version.
  11.  *
  12.  *  This program is distributed in the hope that it will be useful,
  13.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.  *  GNU General Public License for more details.
  16.  *
  17.  *  You should have received a copy of the GNU General Public License
  18.  *  along with this program; if not, write to the Free Software
  19.  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20.  *
  21.  *  Updated 12/97 by Andrew D. Balsa
  22.  *  (see http://www.tux.org/~balsa/linux/cyrix)
  23.  *
  24.  ******************************************************************************
  25.  *
  26.  *  Usage: no parameters! Just typing 6x86_reg at the prompt will dump all 6x86(L)
  27.  *  documented registers to the console. Now of course if you run it on another
  28.  *  processor model don't expect any meaningful results...
  29.  */
  30. #include <stdio.h>
  31. #include <string.h>
  32. #include <unistd.h>
  33. #include <stdarg.h>
  34. #include <stdlib.h>
  35. #include <string.h>
  36. #include <time.h>
  37. //#include <asm/io.h>  not needed by OS/2
  38.  
  39. // start of OS/2 section added
  40. #include <sys/hw.h>
  41. #define outb(data,port) _outp32(port,data)
  42. #define inb(port) _inp32(port)
  43. #define ioperm(x,y,z) (0)
  44. #define VERSION 1.5
  45. // end of OS/2 section
  46.  
  47. typedef int bool;
  48. #ifndef TRUE
  49. #  define TRUE (1)
  50. #endif
  51. #ifndef FALSE
  52. #  define FALSE (0)
  53. #endif
  54. char *CommandName;
  55. char info[256];
  56. void get_IO_range(int start, int len)
  57. {
  58.   if (ioperm(start, len, 1) != 0)
  59.   {
  60.     perror("I/O Permissions");
  61.     fprintf(stderr,"Cannot get I/O permissions for hardware address range 0x%x-0x%x.\n\
  62.              You must be superuser, or the program must be setuid root!\n", start, start+len-1);
  63.     exit(1);
  64.   }
  65. }
  66. char* int_to_bin(int num, int bits)
  67. {
  68.   static char binstr[sizeof(long int)+1];
  69.   int i;
  70.   for (i=0; i<bits; i++) binstr[i] = 0x30; /* char '0' */
  71.   binstr[bits] = 0x00;
  72.   for (i=0; i<bits; i++) binstr[bits-1-i] += ((num >> i) & 0x00000001);
  73.   return(binstr);
  74. }
  75. char *size_str(int kb)
  76. {
  77.   static char size[20];
  78.   if (kb < 1024) sprintf(size, "%d KB", kb);
  79.   else if (kb < 1024*1024) sprintf(size, "%d MB", kb >> 10);
  80.   else sprintf(size, "%d GB", kb >> 20);
  81.   return size;
  82. }
  83. /* the original bogomips code from the Linux kernel */
  84. static __inline__ void delay(int loops)
  85. {
  86.   __asm__(".align 2,0x90\n1:\tdecl %0\n\tjns 1b": :"a" (loops):"ax");
  87. }
  88. /* a short routine to read /proc/cpuinfo */
  89. void read_cpuinfo(void) {
  90.   FILE *in;
  91.   char things[256];
  92.   extern char info[256];
  93.   if ((in=fopen("/proc/cpuinfo","r"))==NULL)
  94.       strcpy(info,"unknown");
  95.   else {
  96.    while (strcmp(things,"bogomips"))
  97.      fscanf(in, "%s", things);   /* skip to the bogomips line */
  98.    fscanf(in, "%s", things);  /* skip the ":" */
  99.    fscanf(in, "%s", info);    /* now this should be the bogomips */
  100.    fclose(in);
  101.   }
  102.   return;
  103. }
  104. /* Register index defines */
  105. #define ARR_BASE 0xC4
  106. #define RCR_BASE 0xDC
  107. #define CCR0 0xC0
  108. #define CCR1 0xC1
  109. #define CCR2 0xC2
  110. #define CCR3 0xC3
  111. #define CCR4 0xE8
  112. #define CCR5 0xE9
  113. #define DIR0 0xFE
  114. #define DIR1 0xFF
  115. /*****************************************************************************/
  116. /* This was a nice short routine before I began messing with it
  117.  * It still has a very linear structure, but the registers on the 6x86 line
  118.  * of CPUs are so irregular that the program got a little bit messy.
  119.  * - Andrew
  120.  */
  121. /*****************************************************************************/
  122. int main (int argc, char* argv[])
  123. {
  124.   int i;
  125.   unsigned int addr, size, rcr, ccr, dir;
  126.   int mapen;
  127.   unsigned long loops_per_sec = 1;
  128.   unsigned long ticks;
  129. /*
  130.  * start doing something useful
  131.  */
  132.    get_IO_range(0x22, 2);
  133.    printf("\n6x86 (Classic/L/MX) Register Dump utility\n\n");
  134.   /* MAPEN **************************************************************/
  135.   outb(0xC3, 0x22); mapen = inb(0x23);
  136.   outb(0xC3, 0x22); outb(mapen | 0x10, 0x23);
  137.   /* DIR0 ***************************************************************/
  138.   outb(DIR0, 0x22); dir = inb(0x23);
  139.   printf("6x86 DIR0: 0x%x\t", dir);
  140.   /* core/bus clock ratio analysis **************************************/
  141.   if ((dir & 0x70) == 0x50)   /* 6x86MX */
  142.   switch (dir & 0x07) {
  143.    case 0x01:
  144.       { printf("2X core/bus clock ratio");
  145.         break;
  146.       }
  147.    case 0x02:
  148.       { printf("2.5X core/bus clock ratio");
  149.         break;
  150.       }
  151.    case 0x03:
  152.       { printf("3X core/bus clock ratio");
  153.         break;
  154.       }
  155.    case 0x04:
  156.       { printf("3.5X core/bus clock ratio");
  157.         break;
  158.       }
  159.   }
  160.   else            /* 6x86(L) */
  161.   switch (dir & 0x05) {
  162.    case 0x00:
  163.       { printf("1X core/bus clock ratio");
  164.         break;
  165.       }
  166.    case 0x01:     /* practically the only one used */
  167.       { printf("2X core/bus clock ratio");
  168.         break;
  169.       }
  170.    case 0x05:
  171.       { printf("3X core/bus clock ratio");
  172.         break;
  173.       }
  174.    case 0x04:
  175.       { printf("4X core/bus clock ratio");
  176.         break;
  177.       }
  178.   }
  179.   printf("\n");
  180.   /* DIR1 ***************************************************************/
  181.   outb(DIR1, 0x22); dir = inb(0x23);
  182.   printf("     DIR1: 0x%x\t", dir);
  183.   /* Processor identification *******************************************/
  184.   switch (dir) {
  185.    case 0x14:
  186.       { printf("6x86 Rev. 2.4");
  187.         break;
  188.       }
  189.    case 0x15:
  190.       { printf("6x86 Rev. 2.5");
  191.         break;
  192.       }
  193.    case 0x16:
  194.       { printf("6x86 Rev. 2.6");
  195.         break;
  196.       }
  197.    case 0x17:
  198.       { printf("6x86 Rev. 2.7 or 3.7");
  199.         break;
  200.       }
  201.    case 0x22:
  202.       { printf("6x86L Rev. 4.2");
  203.         break;
  204.       }
  205.    case 0x03:
  206.       { printf("6x86MX Rev. 1.3");
  207.         break;
  208.       }
  209.    case 0x04:
  210.       { printf("6x86MX Rev. 1.4");
  211.         break;
  212.       }
  213.   }
  214.   /* BogoMIPS calculation ***********************************************/
  215.   printf("\n\nWait a moment...\n");
  216.   /* Now let's take a look at the two bogomips readings */
  217.   /* First we calculate the bogoMIPS reading using exactly
  218.    * the same code as the Linux kernel
  219.    */
  220.    while ((loops_per_sec <<= 1)) {
  221.     ticks = clock();
  222.     delay(loops_per_sec);
  223.     ticks = clock() - ticks;
  224.     if (ticks >= CLOCKS_PER_SEC) {
  225.       loops_per_sec = (loops_per_sec / ticks) * CLOCKS_PER_SEC;
  226.       printf("Calculated BogoMIPS:\t%lu.%02lu\n",
  227.         loops_per_sec/500000,
  228.         (loops_per_sec/5000) % 100
  229.         );
  230.       break;
  231.       }
  232.   }
  233.   /* and now the kernel bogoMIPS, calculated at boot time and
  234.    * reported by /proc/cpuinfo.
  235.    */
  236.   read_cpuinfo();
  237.   printf("Kernel BogoMIPS:\t%s\n", info);
  238.   printf("\n");
  239.   /* CCR ****************************************************************/
  240.   outb(CCR0, 0x22); ccr = inb(0x23);
  241.   printf("6x86 CCR0: 0x%x\t", ccr);
  242.   if (ccr & 0x02) printf("NC1 set (address region 640Kb-1Mb non-cacheable)\n");
  243.   else printf("NC1 reset (address region 640Kb-1Mb cacheable)\n");
  244.   outb(CCR1, 0x22); ccr = inb(0x23);
  245.   printf("     CCR1: 0x%x\t", ccr);
  246.   if (ccr & 0x10) printf("NO_LOCK set\n");
  247.   else printf("NO_LOCK reset\n");
  248.   outb(CCR2, 0x22); ccr = inb(0x23);
  249.   printf("     CCR2: 0x%x\t", ccr);
  250.   if (ccr & 0x08) printf("SUSP_HLT set (low power suspend mode enabled)\n");
  251.   else printf("SUSP_HLT reset (low power suspend mode disabled)\n");
  252.   outb(CCR3, 0x22); ccr = inb(0x23);
  253.   printf("     CCR3: 0x%x\n", ccr);
  254.   outb(CCR4, 0x22); ccr = inb(0x23);
  255.   printf("     CCR4: 0x%x\t", ccr);
  256.   if (dir & 0xf0)    /* if this is a 6x86 or 6x86L */
  257.     if (ccr & 0x10) printf("DTE cache enabled, ");
  258.     else printf("DTE cache disabled, ");
  259.   switch (ccr & 0x07) {
  260.    case 0x00:
  261.       { printf("1 clock cycle I/O recovery time");
  262.         break;
  263.       }
  264.    case 0x01:
  265.       { printf("2 clock cycles I/O recovery time");
  266.         break;
  267.       }
  268.    case 0x02:
  269.       { printf("4 clock cycles I/O recovery time");
  270.         break;
  271.       }
  272.    case 0x03:
  273.       { printf("8 clock cycles I/O recovery time");
  274.         break;
  275.       }
  276.    case 0x04:
  277.       { printf("16 clock cycles I/O recovery time");
  278.         break;
  279.       }
  280.    case 0x05:
  281.       { printf("32 clock cycles I/O recovery time");
  282.         break;
  283.       }
  284.    case 0x06:
  285.       { printf("64 clock cycles I/O recovery time");
  286.         break;
  287.       }
  288.    case 0x07:
  289.       { printf("no I/O recovery time");
  290.         break;
  291.       }
  292.   }
  293.   printf("\n");
  294.   outb(CCR5, 0x22); ccr = inb(0x23);
  295.   printf("     CCR5: 0x%x\t", ccr);
  296.   if (dir & 0xf0)    /* if this is a 6x86 or 6x86L */
  297.     if (ccr & 0x02) printf("slow LOOP enabled, ");
  298.     else printf("slow LOOP disabled, ");
  299.   if (ccr & 0x01) printf("allocate cache lines on write misses\n\n");
  300.   else printf("default cache line allocation policy\n\n");
  301.   /* ARR ****************************************************************/
  302.   printf("6x86 Address Region Register dump:\n");
  303.   for (i=0; i<8; i++)
  304.   {
  305.     outb(ARR_BASE + i*3, 0x22); addr = inb(0x23) << 24;
  306.     outb(ARR_BASE + i*3 + 1, 0x22); addr |= inb(0x23) << 16;
  307.     outb(ARR_BASE + i*3 + 2, 0x22); size = inb(0x23);
  308.     addr |= (size & 0xF0) << 8;
  309.     size &= 0x0F;
  310.     printf("  ARR%d: ", i);
  311.     if (size == 0)
  312.     {
  313.       printf("disabled\n");
  314.       continue;
  315.     }
  316.     else
  317.       printf("address = 0x%X , size = ", addr);
  318.     if (i<7)
  319.     {
  320.       if (size == 15) printf("%s\n", size_str(4*1024*1024));
  321.       else printf("%s\n", size_str(2 << size));
  322.     }
  323.     else
  324.     {
  325.       printf("%s\n", size_str(128 << size));
  326.     }
  327.     /* RCR **************************************************************/
  328.     outb(RCR_BASE + i, 0x22); rcr = inb(0x23);
  329.     printf("    RCR = 0x%X : ", rcr);
  330.     if (i != 7)
  331.       printf("%scached",  (rcr & 0x01) ? "not " : "");
  332.     else
  333.       printf("%scached",  (rcr & 0x01) ? "" : "not ");
  334.     if (dir & 0xf0)     /* if this is a 6x86 or 6x86L */
  335.       if (rcr & 0x2) printf(", weak write ordering");
  336.     if (rcr & 0x4) printf(", weak locking");
  337.     if (rcr & 0x8) printf(", write gathering");
  338.     if (rcr & 0x10) printf(", write through");
  339.     if (rcr & 0x20) printf(", no LBA#");
  340.     printf("\n");
  341.   }
  342.   /* Disable MAPEN ******************************************************/
  343.   outb(0xC3, 0x22); outb(mapen, 0x23);
  344.   return(0);
  345. }
  346.