Hardware/CPU/CPUID.cs
author moel.mich
Sat, 24 Apr 2010 20:19:55 +0000
changeset 93 99fbbbf50357
child 95 249d57f82cf8
permissions -rw-r--r--
Added basic support for ITE IT8712F super I/O chips.
     1 /*
     2   
     3   Version: MPL 1.1/GPL 2.0/LGPL 2.1
     4 
     5   The contents of this file are subject to the Mozilla Public License Version
     6   1.1 (the "License"); you may not use this file except in compliance with
     7   the License. You may obtain a copy of the License at
     8  
     9   http://www.mozilla.org/MPL/
    10 
    11   Software distributed under the License is distributed on an "AS IS" basis,
    12   WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
    13   for the specific language governing rights and limitations under the License.
    14 
    15   The Original Code is the Open Hardware Monitor code.
    16 
    17   The Initial Developer of the Original Code is 
    18   Michael Möller <m.moeller@gmx.ch>.
    19   Portions created by the Initial Developer are Copyright (C) 2009-2010
    20   the Initial Developer. All Rights Reserved.
    21 
    22   Contributor(s):
    23 
    24   Alternatively, the contents of this file may be used under the terms of
    25   either the GNU General Public License Version 2 or later (the "GPL"), or
    26   the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
    27   in which case the provisions of the GPL or the LGPL are applicable instead
    28   of those above. If you wish to allow use of your version of this file only
    29   under the terms of either the GPL or the LGPL, and not to allow others to
    30   use your version of this file under the terms of the MPL, indicate your
    31   decision by deleting the provisions above and replace them with the notice
    32   and other provisions required by the GPL or the LGPL. If you do not delete
    33   the provisions above, a recipient may use your version of this file under
    34   the terms of any one of the MPL, the GPL or the LGPL.
    35  
    36 */
    37 
    38 using System;
    39 using System.Collections.Generic;
    40 using System.Text;
    41 
    42 namespace OpenHardwareMonitor.Hardware.CPU {
    43   
    44   public enum Vendor {
    45     Unknown,
    46     Intel,
    47     AMD,
    48   }
    49   
    50   public class CPUID {
    51 
    52     private int thread;
    53 
    54     private uint maxCpuid = 0;
    55     private uint maxCpuidExt = 0;
    56 
    57     private Vendor vendor;
    58 
    59     private string cpuBrandString;
    60     private string name;
    61 
    62     private uint[,] cpuidData;
    63     private uint[,] cpuidExtData;
    64 
    65     private uint family;
    66     private uint model;
    67     private uint stepping;
    68 
    69     private uint apicId;
    70 
    71     private uint threadMaskWith;
    72     private uint coreMaskWith;
    73 
    74     private uint processorId;
    75     private uint coreId;
    76     private uint threadId;
    77 
    78     public static uint CPUID_0 = 0;
    79     public static uint CPUID_EXT = 0x80000000;
    80 
    81     private void AppendRegister(StringBuilder b, uint value) {
    82       b.Append((char)((value) & 0xff));
    83       b.Append((char)((value >> 8) & 0xff));
    84       b.Append((char)((value >> 16) & 0xff));
    85       b.Append((char)((value >> 24) & 0xff));
    86     }
    87 
    88     public CPUID(int thread) {
    89       this.thread = thread;
    90 
    91       uint eax, ebx, ecx, edx;
    92 
    93       UIntPtr mask = (UIntPtr)(1L << thread);
    94 
    95       if (WinRing0.CpuidTx(CPUID_0, 0,
    96           out eax, out ebx, out ecx, out edx, mask)) {
    97         maxCpuid = eax;
    98         StringBuilder vendorBuilder = new StringBuilder();
    99         AppendRegister(vendorBuilder, ebx);
   100         AppendRegister(vendorBuilder, edx);
   101         AppendRegister(vendorBuilder, ecx);
   102         string cpuVendor = vendorBuilder.ToString();
   103         switch (cpuVendor) {
   104           case "GenuineIntel":
   105             vendor = Vendor.Intel;
   106             break;
   107           case "AuthenticAMD":
   108             vendor = Vendor.AMD;
   109             break;
   110           default:
   111             vendor = Vendor.Unknown;
   112             break;
   113         }
   114         eax = ebx = ecx = edx = 0;
   115         if (WinRing0.CpuidTx(CPUID_EXT, 0,
   116           out eax, out ebx, out ecx, out edx, mask))
   117           maxCpuidExt = eax - CPUID_EXT;
   118       } else {
   119         throw new ArgumentException();
   120       }
   121 
   122       if (maxCpuid == 0 || maxCpuidExt == 0)
   123         return;
   124 
   125       cpuidData = new uint[maxCpuid + 1, 4];
   126       for (uint i = 0; i < (maxCpuid + 1); i++)
   127         WinRing0.CpuidTx(CPUID_0 + i, 0, 
   128           out cpuidData[i, 0], out cpuidData[i, 1],
   129           out cpuidData[i, 2], out cpuidData[i, 3], mask);
   130 
   131       cpuidExtData = new uint[MaxCpuidExt + 1, 4];
   132       for (uint i = 0; i < (MaxCpuidExt + 1); i++)
   133         WinRing0.CpuidTx(CPUID_EXT + i, 0, 
   134           out cpuidExtData[i, 0], out cpuidExtData[i, 1], 
   135           out cpuidExtData[i, 2], out cpuidExtData[i, 3], mask);
   136 
   137       StringBuilder nameBuilder = new StringBuilder();
   138       for (uint i = 2; i <= 4; i++) {
   139         if (WinRing0.CpuidTx(CPUID_EXT + i, 0, 
   140           out eax, out ebx, out ecx, out edx, mask)) 
   141         {
   142           AppendRegister(nameBuilder, eax);
   143           AppendRegister(nameBuilder, ebx);
   144           AppendRegister(nameBuilder, ecx);
   145           AppendRegister(nameBuilder, edx);
   146         }
   147       }
   148       nameBuilder.Replace('\0', ' ');
   149       cpuBrandString = nameBuilder.ToString().Trim();
   150       nameBuilder.Replace("(R)", " ");
   151       nameBuilder.Replace("(TM)", " ");
   152       nameBuilder.Replace("(tm)", " ");
   153       nameBuilder.Replace("CPU", "");
   154       for (int i = 0; i < 10; i++) nameBuilder.Replace("  ", " ");
   155       name = nameBuilder.ToString();
   156       if (name.Contains("@"))
   157         name = name.Remove(name.LastIndexOf('@'));
   158       name = name.Trim();
   159 
   160       this.family = ((cpuidData[1, 0] & 0x0FF00000) >> 20) +
   161         ((cpuidData[1, 0] & 0x0F00) >> 8);
   162       this.model = ((cpuidData[1, 0] & 0x0F0000) >> 12) +
   163         ((cpuidData[1, 0] & 0xF0) >> 4);
   164       this.stepping = (cpuidData[1, 0] & 0x0F);
   165 
   166       this.apicId = (cpuidData[1, 1] >> 24) & 0xFF;
   167 
   168       switch (vendor) {
   169         case Vendor.Intel:
   170           uint maxCoreAndThreadIdPerPackage = (cpuidData[1, 1] >> 16) & 0xFF;
   171           uint maxCoreIdPerPackage = ((cpuidData[4, 0] >> 26) & 0x3F) + 1;
   172           threadMaskWith = (uint)Math.Ceiling(Math.Log(
   173             maxCoreAndThreadIdPerPackage / maxCoreIdPerPackage, 2));
   174           coreMaskWith = (uint)Math.Ceiling(Math.Log(maxCoreIdPerPackage, 2));
   175           break;
   176         case Vendor.AMD:
   177           uint corePerPackage = (cpuidExtData[8, 2] & 0xFF) + 1;
   178           threadMaskWith = 0;
   179           coreMaskWith = (uint)Math.Ceiling(Math.Log(corePerPackage, 2));
   180           break;
   181         default:
   182           threadMaskWith = 0;
   183           coreMaskWith = 0;
   184           break;
   185       }
   186 
   187       processorId = (uint)(apicId >> (int)(coreMaskWith + threadMaskWith));
   188       coreId = (uint)((apicId >> (int)(threadMaskWith)) - processorId);
   189       threadId = apicId - processorId - coreId;
   190     }
   191 
   192     public string Name {
   193       get { return name; }
   194     }
   195 
   196     public string BrandString {
   197       get { return cpuBrandString; }
   198     }
   199 
   200     public int Thread {
   201       get { return thread; }
   202     }
   203 
   204     public uint MaxCPUID {
   205       get { return maxCpuid; }
   206     }
   207 
   208     public uint MaxCpuidExt {
   209       get { return maxCpuidExt; }
   210     }
   211 
   212     public Vendor Vendor {
   213       get { return vendor; }
   214     }
   215 
   216     public uint Family {
   217       get { return family; }
   218     }
   219 
   220     public uint Model {
   221       get { return model; }
   222     }
   223 
   224     public uint Stepping {
   225       get { return stepping; }
   226     }
   227 
   228     public uint ApicId {
   229       get { return apicId; }
   230     }
   231 
   232     public uint ProcessorId {
   233       get { return processorId; }
   234     }
   235 
   236     public uint CoreId {
   237       get { return coreId; }
   238     }
   239 
   240     public uint ThreadId {
   241       get { return threadId; }
   242     }
   243 
   244     public uint[,] Data {
   245       get { return cpuidData; }
   246     }
   247 
   248     public uint[,] ExtData {
   249       get { return cpuidExtData; }
   250     }
   251   }
   252 }