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