Hardware/CPU/CPUID.cs
author sl
Sun, 03 Feb 2013 18:01:50 +0100
changeset 391 ca4c0e7ae75d
parent 329 756af5ee409e
permissions -rw-r--r--
Converted project to VisualStudio 2012.
Adding SoundGraphDisplay and SensorFrontView classes.
They were respectively based on SystemTray and SensorNotifyIcon.
SoundGraphDisplay is now able to load iMONDisplay.dll providing it lives on your PATH.
Adding option to sensor context menu for adding it into FrontView.
     1 /*
     2  
     3   This Source Code Form is subject to the terms of the Mozilla Public
     4   License, v. 2.0. If a copy of the MPL was not distributed with this
     5   file, You can obtain one at http://mozilla.org/MPL/2.0/.
     6  
     7   Copyright (C) 2009-2010 Michael Möller <mmoeller@openhardwaremonitor.org>
     8 	
     9 */
    10 
    11 using System;
    12 using System.Text;
    13 
    14 namespace OpenHardwareMonitor.Hardware.CPU {
    15 
    16   internal enum Vendor {
    17     Unknown,
    18     Intel,
    19     AMD,
    20   }
    21 
    22   internal class CPUID {
    23 
    24     private readonly int thread;
    25 
    26     private readonly Vendor vendor = Vendor.Unknown;
    27 
    28     private readonly string cpuBrandString = "";
    29     private readonly string name = "";
    30 
    31     private readonly uint[,] cpuidData = new uint[0, 0];
    32     private readonly uint[,] cpuidExtData = new uint[0, 0];
    33 
    34     private readonly uint family;
    35     private readonly uint model;
    36     private readonly uint stepping;
    37 
    38     private readonly uint apicId;
    39 
    40     private readonly uint threadMaskWith;
    41     private readonly uint coreMaskWith;
    42 
    43     private readonly uint processorId;
    44     private readonly uint coreId;
    45     private readonly uint threadId;
    46 
    47     public const uint CPUID_0 = 0;
    48     public const uint CPUID_EXT = 0x80000000;
    49 
    50     private static void AppendRegister(StringBuilder b, uint value) {
    51       b.Append((char)((value) & 0xff));
    52       b.Append((char)((value >> 8) & 0xff));
    53       b.Append((char)((value >> 16) & 0xff));
    54       b.Append((char)((value >> 24) & 0xff));
    55     }
    56 
    57     private static uint NextLog2(long x) {
    58       if (x <= 0)
    59         return 0;
    60 
    61       x--;
    62       uint count = 0;
    63       while (x > 0) {
    64         x >>= 1;
    65         count++;
    66       }
    67 
    68       return count;
    69     }
    70 
    71     public CPUID(int thread) {
    72       this.thread = thread;
    73 
    74       uint maxCpuid = 0;
    75       uint maxCpuidExt = 0;
    76 
    77       uint eax, ebx, ecx, edx;
    78 
    79       if (thread >= 32)
    80         throw new ArgumentOutOfRangeException("thread");
    81       ulong mask = 1UL << thread;
    82 
    83       if (Opcode.CpuidTx(CPUID_0, 0,
    84           out eax, out ebx, out ecx, out edx, mask)) {
    85         if (eax > 0)
    86           maxCpuid = eax;
    87         else
    88           return;
    89 
    90         StringBuilder vendorBuilder = new StringBuilder();
    91         AppendRegister(vendorBuilder, ebx);
    92         AppendRegister(vendorBuilder, edx);
    93         AppendRegister(vendorBuilder, ecx);
    94         string cpuVendor = vendorBuilder.ToString();
    95         switch (cpuVendor) {
    96           case "GenuineIntel":
    97             vendor = Vendor.Intel;
    98             break;
    99           case "AuthenticAMD":
   100             vendor = Vendor.AMD;
   101             break;
   102           default:
   103             vendor = Vendor.Unknown;
   104             break;
   105         }
   106         eax = ebx = ecx = edx = 0;
   107         if (Opcode.CpuidTx(CPUID_EXT, 0,
   108           out eax, out ebx, out ecx, out edx, mask)) {
   109           if (eax > CPUID_EXT)
   110             maxCpuidExt = eax - CPUID_EXT;
   111           else
   112             return;
   113         } else {
   114           throw new ArgumentOutOfRangeException("thread");
   115         }
   116       } else {
   117         throw new ArgumentOutOfRangeException("thread");
   118       }
   119 
   120       maxCpuid = Math.Min(maxCpuid, 1024);
   121       maxCpuidExt = Math.Min(maxCpuidExt, 1024);   
   122 
   123       cpuidData = new uint[maxCpuid + 1, 4];
   124       for (uint i = 0; i < (maxCpuid + 1); i++)
   125         Opcode.CpuidTx(CPUID_0 + i, 0, 
   126           out cpuidData[i, 0], out cpuidData[i, 1],
   127           out cpuidData[i, 2], out cpuidData[i, 3], mask);
   128 
   129       cpuidExtData = new uint[maxCpuidExt + 1, 4];
   130       for (uint i = 0; i < (maxCpuidExt + 1); i++)
   131         Opcode.CpuidTx(CPUID_EXT + i, 0, 
   132           out cpuidExtData[i, 0], out cpuidExtData[i, 1], 
   133           out cpuidExtData[i, 2], out cpuidExtData[i, 3], mask);
   134 
   135       StringBuilder nameBuilder = new StringBuilder();
   136       for (uint i = 2; i <= 4; i++) {
   137         if (Opcode.CpuidTx(CPUID_EXT + i, 0, 
   138           out eax, out ebx, out ecx, out edx, mask)) 
   139         {
   140           AppendRegister(nameBuilder, eax);
   141           AppendRegister(nameBuilder, ebx);
   142           AppendRegister(nameBuilder, ecx);
   143           AppendRegister(nameBuilder, edx);
   144         }
   145       }
   146       nameBuilder.Replace('\0', ' ');
   147       cpuBrandString = nameBuilder.ToString().Trim();
   148       nameBuilder.Replace("(R)", " ");
   149       nameBuilder.Replace("(TM)", " ");
   150       nameBuilder.Replace("(tm)", "");
   151       nameBuilder.Replace("CPU", "");
   152       nameBuilder.Replace("Quad-Core Processor", "");
   153       nameBuilder.Replace("Six-Core Processor", "");
   154       nameBuilder.Replace("Eight-Core Processor", "");
   155       for (int i = 0; i < 10; i++) nameBuilder.Replace("  ", " ");
   156       name = nameBuilder.ToString();
   157       if (name.Contains("@"))
   158         name = name.Remove(name.LastIndexOf('@'));
   159       name = name.Trim();      
   160 
   161       this.family = ((cpuidData[1, 0] & 0x0FF00000) >> 20) +
   162         ((cpuidData[1, 0] & 0x0F00) >> 8);
   163       this.model = ((cpuidData[1, 0] & 0x0F0000) >> 12) +
   164         ((cpuidData[1, 0] & 0xF0) >> 4);
   165       this.stepping = (cpuidData[1, 0] & 0x0F);
   166 
   167       this.apicId = (cpuidData[1, 1] >> 24) & 0xFF;
   168 
   169       switch (vendor) {
   170         case Vendor.Intel:
   171           uint maxCoreAndThreadIdPerPackage = (cpuidData[1, 1] >> 16) & 0xFF;
   172           uint maxCoreIdPerPackage;
   173           if (maxCpuid >= 4)
   174             maxCoreIdPerPackage = ((cpuidData[4, 0] >> 26) & 0x3F) + 1;
   175           else
   176             maxCoreIdPerPackage = 1;
   177           threadMaskWith = 
   178             NextLog2(maxCoreAndThreadIdPerPackage / maxCoreIdPerPackage);
   179           coreMaskWith = NextLog2(maxCoreIdPerPackage);
   180           break;
   181         case Vendor.AMD:
   182           uint corePerPackage;
   183           if (maxCpuidExt >= 8)
   184             corePerPackage = (cpuidExtData[8, 2] & 0xFF) + 1;
   185           else
   186             corePerPackage = 1;
   187           threadMaskWith = 0;
   188           coreMaskWith = NextLog2(corePerPackage);
   189           break;
   190         default:
   191           threadMaskWith = 0;
   192           coreMaskWith = 0;
   193           break;
   194       }
   195 
   196       processorId = (apicId >> (int)(coreMaskWith + threadMaskWith));
   197       coreId = ((apicId >> (int)(threadMaskWith)) 
   198         - (processorId << (int)(coreMaskWith)));
   199       threadId = apicId
   200         - (processorId << (int)(coreMaskWith + threadMaskWith))
   201         - (coreId << (int)(threadMaskWith)); 
   202     }
   203 
   204     public string Name {
   205       get { return name; }
   206     }
   207 
   208     public string BrandString {
   209       get { return cpuBrandString; }
   210     }
   211 
   212     public int Thread {
   213       get { return thread; }
   214     }
   215 
   216     public Vendor Vendor {
   217       get { return vendor; }
   218     }
   219 
   220     public uint Family {
   221       get { return family; }
   222     }
   223 
   224     public uint Model {
   225       get { return model; }
   226     }
   227 
   228     public uint Stepping {
   229       get { return stepping; }
   230     }
   231 
   232     public uint ApicId {
   233       get { return apicId; }
   234     }
   235 
   236     public uint ProcessorId {
   237       get { return processorId; }
   238     }
   239 
   240     public uint CoreId {
   241       get { return coreId; }
   242     }
   243 
   244     public uint ThreadId {
   245       get { return threadId; }
   246     }
   247 
   248     public uint[,] Data {
   249       get { return cpuidData; }
   250     }
   251 
   252     public uint[,] ExtData {
   253       get { return cpuidExtData; }
   254     }
   255   }
   256 }