Hardware/CPU/CPUGroup.cs
author moel.mich
Tue, 09 Mar 2010 22:27:10 +0000
changeset 79 9cdbe1d8d12a
parent 36 32adc68f54f8
child 90 3333b29a1746
permissions -rw-r--r--
Changed the CPU clock calculation. If no invariant TSC is available, then the max CPU clock is estimated at startup under load, otherwise an average over one second is used.
moel@1
     1
/*
moel@1
     2
  
moel@1
     3
  Version: MPL 1.1/GPL 2.0/LGPL 2.1
moel@1
     4
moel@1
     5
  The contents of this file are subject to the Mozilla Public License Version
moel@1
     6
  1.1 (the "License"); you may not use this file except in compliance with
moel@1
     7
  the License. You may obtain a copy of the License at
moel@1
     8
 
moel@1
     9
  http://www.mozilla.org/MPL/
moel@1
    10
moel@1
    11
  Software distributed under the License is distributed on an "AS IS" basis,
moel@1
    12
  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
moel@1
    13
  for the specific language governing rights and limitations under the License.
moel@1
    14
moel@1
    15
  The Original Code is the Open Hardware Monitor code.
moel@1
    16
moel@1
    17
  The Initial Developer of the Original Code is 
moel@1
    18
  Michael Möller <m.moeller@gmx.ch>.
moel@1
    19
  Portions created by the Initial Developer are Copyright (C) 2009-2010
moel@1
    20
  the Initial Developer. All Rights Reserved.
moel@1
    21
moel@1
    22
  Contributor(s):
moel@1
    23
moel@1
    24
  Alternatively, the contents of this file may be used under the terms of
moel@1
    25
  either the GNU General Public License Version 2 or later (the "GPL"), or
moel@1
    26
  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
moel@1
    27
  in which case the provisions of the GPL or the LGPL are applicable instead
moel@1
    28
  of those above. If you wish to allow use of your version of this file only
moel@1
    29
  under the terms of either the GPL or the LGPL, and not to allow others to
moel@1
    30
  use your version of this file under the terms of the MPL, indicate your
moel@1
    31
  decision by deleting the provisions above and replace them with the notice
moel@1
    32
  and other provisions required by the GPL or the LGPL. If you do not delete
moel@1
    33
  the provisions above, a recipient may use your version of this file under
moel@1
    34
  the terms of any one of the MPL, the GPL or the LGPL.
moel@1
    35
 
moel@1
    36
*/
moel@1
    37
moel@1
    38
using System;
moel@1
    39
using System.Collections.Generic;
moel@1
    40
using System.Text;
moel@1
    41
moel@1
    42
namespace OpenHardwareMonitor.Hardware.CPU {
moel@1
    43
moel@1
    44
  public class CPUGroup : IGroup { 
moel@1
    45
    private List<IHardware> hardware = new List<IHardware>();
moel@1
    46
moel@1
    47
    private string cpuBrandString;
moel@1
    48
    private string cpuVendor;
moel@1
    49
    private uint[,] cpuidData;
moel@1
    50
    private uint[,] cpuidExtData;
moel@1
    51
moel@1
    52
    private uint family;
moel@1
    53
    private uint model;
moel@1
    54
    private uint stepping;
moel@1
    55
moel@1
    56
    private static uint CPUID = 0;
moel@1
    57
    private static uint CPUID_EXT = 0x80000000;
moel@1
    58
moel@1
    59
    public static void AppendRegister(StringBuilder b, uint value) {
moel@1
    60
      b.Append((char)((value) & 0xff));
moel@1
    61
      b.Append((char)((value >> 8) & 0xff));
moel@1
    62
      b.Append((char)((value >> 16) & 0xff));
moel@1
    63
      b.Append((char)((value >> 24) & 0xff));
moel@1
    64
    }
moel@1
    65
moel@1
    66
    public CPUGroup() {
moel@1
    67
moel@1
    68
      if (!WinRing0.IsAvailable) 
moel@1
    69
        return;
moel@1
    70
moel@1
    71
      if (WinRing0.IsCpuid()) {
moel@1
    72
        uint maxCPUID = 0;
moel@1
    73
        uint maxCPUID_EXT = 0;
moel@1
    74
        uint eax, ebx, ecx, edx;
moel@1
    75
moel@1
    76
        
moel@1
    77
        if (WinRing0.Cpuid(CPUID, out eax, out ebx, out ecx, out edx)) {
moel@1
    78
          maxCPUID = eax;
moel@1
    79
          StringBuilder vendorBuilder = new StringBuilder();
moel@1
    80
          AppendRegister(vendorBuilder, ebx);
moel@1
    81
          AppendRegister(vendorBuilder, edx);
moel@1
    82
          AppendRegister(vendorBuilder, ecx);
moel@1
    83
          cpuVendor = vendorBuilder.ToString();
moel@1
    84
moel@1
    85
          eax = ebx = ecx = edx = 0;
moel@1
    86
          if (WinRing0.Cpuid(CPUID_EXT, out eax, out ebx, out ecx, out edx)) {
moel@1
    87
            maxCPUID_EXT = eax - CPUID_EXT;
moel@1
    88
          }
moel@1
    89
        }
moel@1
    90
        if (maxCPUID == 0 || maxCPUID_EXT == 0)
moel@1
    91
          return;        
moel@1
    92
moel@1
    93
        cpuidData = new uint[maxCPUID + 1, 4];
moel@1
    94
        for (uint i = 0; i < (maxCPUID + 1); i++)
moel@1
    95
          WinRing0.Cpuid(CPUID + i, out cpuidData[i, 0], out cpuidData[i, 1],
moel@1
    96
            out cpuidData[i, 2], out cpuidData[i, 3]);
moel@1
    97
moel@1
    98
        cpuidExtData = new uint[maxCPUID_EXT + 1, 4];
moel@1
    99
        for (uint i = 0; i < (maxCPUID_EXT + 1); i++)
moel@1
   100
          WinRing0.Cpuid(CPUID_EXT + i, out cpuidExtData[i, 0],
moel@1
   101
            out cpuidExtData[i, 1], out cpuidExtData[i, 2],
moel@1
   102
            out cpuidExtData[i, 3]);
moel@1
   103
moel@1
   104
        StringBuilder nameBuilder = new StringBuilder();
moel@1
   105
        for (uint i = 2; i <= 4; i++) {
moel@1
   106
          if (WinRing0.Cpuid(CPUID_EXT + i, out eax, out ebx, out ecx, out edx)) 
moel@1
   107
          {
moel@1
   108
            AppendRegister(nameBuilder, eax);
moel@1
   109
            AppendRegister(nameBuilder, ebx);
moel@1
   110
            AppendRegister(nameBuilder, ecx);
moel@1
   111
            AppendRegister(nameBuilder, edx);
moel@1
   112
          }
moel@1
   113
        }
moel@36
   114
        nameBuilder.Replace('\0', ' ');
moel@36
   115
        cpuBrandString = nameBuilder.ToString().Trim();
moel@1
   116
        nameBuilder.Replace("(R)", " ");
moel@1
   117
        nameBuilder.Replace("(TM)", " ");
moel@1
   118
        nameBuilder.Replace("(tm)", " ");
moel@1
   119
        nameBuilder.Replace("CPU", "");
moel@1
   120
        for (int i = 0; i < 10; i++) nameBuilder.Replace("  ", " ");
moel@1
   121
        string name = nameBuilder.ToString();
moel@1
   122
        if (name.Contains("@"))
moel@1
   123
          name = name.Remove(name.LastIndexOf('@')); 
moel@1
   124
        name = name.Trim();
moel@1
   125
moel@1
   126
        this.family = ((cpuidData[1, 0] & 0x0FF00000) >> 20) +
moel@1
   127
          ((cpuidData[1, 0] & 0x0F00) >> 8);
moel@1
   128
        this.model = ((cpuidData[1, 0] & 0x0F0000) >> 12) +
moel@1
   129
          ((cpuidData[1, 0] & 0xF0) >> 4);
moel@1
   130
        this.stepping = (cpuidData[1, 0] & 0x0F);
moel@1
   131
moel@1
   132
        switch (cpuVendor) {
moel@1
   133
          case "GenuineIntel":
moel@44
   134
            hardware.Add(new IntelCPU(name, family, model, stepping, 
moel@44
   135
              cpuidData, cpuidExtData));
moel@1
   136
            break;
moel@1
   137
          case "AuthenticAMD":                       
moel@1
   138
            // check if processor supports a digital thermal sensor            
moel@1
   139
            if (maxCPUID_EXT >= 7 && (cpuidExtData[7, 3] & 1) != 0) {
moel@1
   140
              switch (family) {
moel@14
   141
                case 0x0F:
moel@14
   142
                  hardware.Add(new AMD0FCPU(name, family, model, stepping,
moel@14
   143
                    cpuidData, cpuidExtData));
moel@14
   144
                  break;
moel@1
   145
                case 0x10:
moel@1
   146
                  hardware.Add(new AMD10CPU(name, family, model, stepping,
moel@1
   147
                    cpuidData, cpuidExtData));
moel@1
   148
                  break;
moel@1
   149
                default:
moel@1
   150
                  break;
moel@1
   151
              }
moel@1
   152
            }
moel@1
   153
            break;
moel@1
   154
          default:
moel@1
   155
            break;
moel@1
   156
        }
moel@1
   157
      }
moel@1
   158
    }
moel@1
   159
moel@1
   160
    public IHardware[] Hardware {
moel@1
   161
      get {
moel@1
   162
        return hardware.ToArray();
moel@1
   163
      }
moel@1
   164
    }
moel@1
   165
moel@1
   166
    private void AppendCpuidData(StringBuilder r, uint[,] data, uint offset) {
moel@1
   167
      for (int i = 0; i < data.GetLength(0); i++) {
moel@1
   168
        r.Append(" ");
moel@1
   169
        r.Append((i + offset).ToString("X8"));
moel@1
   170
        for (int j = 0; j < 4; j++) {
moel@1
   171
          r.Append("  ");
moel@1
   172
          r.Append(data[i, j].ToString("X8"));
moel@1
   173
        }
moel@1
   174
        r.AppendLine();
moel@1
   175
      }
moel@1
   176
    }
moel@1
   177
moel@1
   178
    public string GetReport() {
moel@1
   179
moel@1
   180
      StringBuilder r = new StringBuilder();
moel@1
   181
moel@1
   182
      r.AppendLine("CPUID");
moel@1
   183
      r.AppendLine();
moel@1
   184
      r.AppendFormat("Processor Vendor: {0}{1}", cpuVendor, 
moel@1
   185
        Environment.NewLine);
moel@1
   186
      r.AppendFormat("Processor Brand: {0}{1}", cpuBrandString, 
moel@1
   187
        Environment.NewLine);
moel@1
   188
      r.AppendFormat("Family: 0x{0}{1}", family.ToString("X"),
moel@1
   189
        Environment.NewLine);
moel@1
   190
      r.AppendFormat("Model: 0x{0}{1}", model.ToString("X"),
moel@1
   191
        Environment.NewLine);
moel@1
   192
      r.AppendFormat("Stepping: 0x{0}{1}", stepping.ToString("X"),
moel@1
   193
        Environment.NewLine);
moel@1
   194
      r.AppendLine();
moel@1
   195
moel@1
   196
      r.AppendLine("CPUID Return Values");
moel@1
   197
      r.AppendLine();
moel@1
   198
moel@18
   199
      if (cpuidData != null) {
moel@18
   200
        r.AppendLine(" Function  EAX       EBX       ECX       EDX");
moel@18
   201
        AppendCpuidData(r, cpuidData, CPUID);
moel@18
   202
        AppendCpuidData(r, cpuidExtData, CPUID_EXT);
moel@18
   203
        r.AppendLine();
moel@18
   204
      }
moel@1
   205
moel@1
   206
      return r.ToString();
moel@1
   207
    }
moel@1
   208
moel@1
   209
    public void Close() { }
moel@1
   210
  }
moel@1
   211
}