| 
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@90
 | 
    40  | 
using System.Diagnostics;
  | 
| 
moel@1
 | 
    41  | 
using System.Text;
  | 
| 
moel@1
 | 
    42  | 
  | 
| 
moel@1
 | 
    43  | 
namespace OpenHardwareMonitor.Hardware.CPU {
 | 
| 
moel@1
 | 
    44  | 
  | 
| 
moel@1
 | 
    45  | 
  public class CPUGroup : IGroup { 
 | 
| 
moel@1
 | 
    46  | 
    private List<IHardware> hardware = new List<IHardware>();
  | 
| 
moel@1
 | 
    47  | 
  | 
| 
moel@90
 | 
    48  | 
    private CPUID[][][] threads;
  | 
| 
moel@1
 | 
    49  | 
  | 
| 
moel@90
 | 
    50  | 
    private CPUID[][] GetProcessorThreads() {
 | 
| 
moel@1
 | 
    51  | 
  | 
| 
moel@90
 | 
    52  | 
      List<CPUID> threads = new List<CPUID>();
  | 
| 
moel@90
 | 
    53  | 
      for (int i = 0; i < 32; i++) {
 | 
| 
moel@90
 | 
    54  | 
        try {
 | 
| 
moel@90
 | 
    55  | 
          threads.Add(new CPUID(i));
  | 
| 
moel@90
 | 
    56  | 
        } catch (ArgumentException) { }
 | 
| 
moel@90
 | 
    57  | 
      }
  | 
| 
moel@1
 | 
    58  | 
  | 
| 
moel@90
 | 
    59  | 
      SortedDictionary<uint, List<CPUID>> processors =
  | 
| 
moel@90
 | 
    60  | 
        new SortedDictionary<uint, List<CPUID>>();
  | 
| 
moel@90
 | 
    61  | 
      foreach (CPUID thread in threads) {
 | 
| 
moel@90
 | 
    62  | 
        List<CPUID> list;
  | 
| 
moel@90
 | 
    63  | 
        processors.TryGetValue(thread.ProcessorId, out list);
  | 
| 
moel@90
 | 
    64  | 
        if (list == null) {
 | 
| 
moel@90
 | 
    65  | 
          list = new List<CPUID>();
  | 
| 
moel@90
 | 
    66  | 
          processors.Add(thread.ProcessorId, list);
  | 
| 
moel@90
 | 
    67  | 
        }
  | 
| 
moel@90
 | 
    68  | 
        list.Add(thread);
  | 
| 
moel@90
 | 
    69  | 
      }
  | 
| 
moel@90
 | 
    70  | 
  | 
| 
moel@90
 | 
    71  | 
      CPUID[][] processorThreads = new CPUID[processors.Count][];
  | 
| 
moel@90
 | 
    72  | 
      int index = 0;
  | 
| 
moel@90
 | 
    73  | 
      foreach (List<CPUID> list in processors.Values) {
 | 
| 
moel@90
 | 
    74  | 
        processorThreads[index] = list.ToArray();
  | 
| 
moel@90
 | 
    75  | 
        index++;
  | 
| 
moel@90
 | 
    76  | 
      }
  | 
| 
moel@90
 | 
    77  | 
      return processorThreads;
  | 
| 
moel@90
 | 
    78  | 
    }
  | 
| 
moel@90
 | 
    79  | 
  | 
| 
moel@90
 | 
    80  | 
    private CPUID[][] GroupThreadsByCore(CPUID[] threads) {
 | 
| 
moel@90
 | 
    81  | 
  | 
| 
moel@90
 | 
    82  | 
      SortedDictionary<uint, List<CPUID>> cores = 
  | 
| 
moel@90
 | 
    83  | 
        new SortedDictionary<uint, List<CPUID>>();
  | 
| 
moel@90
 | 
    84  | 
      foreach (CPUID thread in threads) {
 | 
| 
moel@90
 | 
    85  | 
        List<CPUID> coreList;
  | 
| 
moel@90
 | 
    86  | 
        cores.TryGetValue(thread.CoreId, out coreList);
  | 
| 
moel@90
 | 
    87  | 
        if (coreList == null) {
 | 
| 
moel@90
 | 
    88  | 
          coreList = new List<CPUID>();
  | 
| 
moel@90
 | 
    89  | 
          cores.Add(thread.CoreId, coreList);
  | 
| 
moel@90
 | 
    90  | 
        }
  | 
| 
moel@90
 | 
    91  | 
        coreList.Add(thread);
  | 
| 
moel@90
 | 
    92  | 
      }
  | 
| 
moel@90
 | 
    93  | 
  | 
| 
moel@90
 | 
    94  | 
      CPUID[][] coreThreads = new CPUID[cores.Count][];
  | 
| 
moel@90
 | 
    95  | 
      int index = 0;
  | 
| 
moel@90
 | 
    96  | 
      foreach (List<CPUID> list in cores.Values) {
 | 
| 
moel@90
 | 
    97  | 
        coreThreads[index] = list.ToArray();
  | 
| 
moel@90
 | 
    98  | 
        index++;
  | 
| 
moel@90
 | 
    99  | 
      }
  | 
| 
moel@90
 | 
   100  | 
      return coreThreads;
  | 
| 
moel@1
 | 
   101  | 
    }
  | 
| 
moel@1
 | 
   102  | 
  | 
| 
moel@1
 | 
   103  | 
    public CPUGroup() {
 | 
| 
moel@90
 | 
   104  | 
      if (!WinRing0.IsCpuid())
  | 
| 
moel@1
 | 
   105  | 
        return;
  | 
| 
moel@1
 | 
   106  | 
  | 
| 
moel@90
 | 
   107  | 
      CPUID[][] processorThreads = GetProcessorThreads();
  | 
| 
moel@90
 | 
   108  | 
      this.threads = new CPUID[processorThreads.Length][][];
  | 
| 
moel@1
 | 
   109  | 
  | 
| 
moel@90
 | 
   110  | 
      int index = 0;
  | 
| 
moel@90
 | 
   111  | 
      foreach (CPUID[] threads in processorThreads) {
 | 
| 
moel@90
 | 
   112  | 
        if (threads.Length == 0)
  | 
| 
moel@90
 | 
   113  | 
          continue;
  | 
| 
moel@90
 | 
   114  | 
            
  | 
| 
moel@90
 | 
   115  | 
        CPUID[][] coreThreads = GroupThreadsByCore(threads);
  | 
| 
moel@1
 | 
   116  | 
  | 
| 
moel@90
 | 
   117  | 
        this.threads[index] = coreThreads;
  | 
| 
moel@90
 | 
   118  | 
        index++;
  | 
| 
moel@1
 | 
   119  | 
  | 
| 
moel@90
 | 
   120  | 
        switch (threads[0].Vendor) {
 | 
| 
moel@90
 | 
   121  | 
          case Vendor.Intel:
  | 
| 
moel@90
 | 
   122  | 
            hardware.Add(new IntelCPU(coreThreads));
  | 
| 
moel@1
 | 
   123  | 
            break;
  | 
| 
moel@90
 | 
   124  | 
          case Vendor.AMD:
  | 
| 
moel@90
 | 
   125  | 
            switch (threads[0].Family) {
 | 
| 
moel@90
 | 
   126  | 
              case 0x0F:
  | 
| 
moel@90
 | 
   127  | 
                hardware.Add(new AMD0FCPU(coreThreads));
  | 
| 
moel@90
 | 
   128  | 
                break;
  | 
| 
moel@90
 | 
   129  | 
              case 0x10:
  | 
| 
moel@90
 | 
   130  | 
                hardware.Add(new AMD10CPU(coreThreads));
  | 
| 
moel@90
 | 
   131  | 
                break;
  | 
| 
moel@90
 | 
   132  | 
              default:
  | 
| 
moel@90
 | 
   133  | 
                break;
  | 
| 
moel@90
 | 
   134  | 
            } break;
  | 
| 
moel@1
 | 
   135  | 
          default:
  | 
| 
moel@1
 | 
   136  | 
            break;
  | 
| 
moel@90
 | 
   137  | 
        } 
  | 
| 
moel@1
 | 
   138  | 
      }
  | 
| 
moel@1
 | 
   139  | 
    }
  | 
| 
moel@90
 | 
   140  | 
    
  | 
| 
moel@1
 | 
   141  | 
    public IHardware[] Hardware {
 | 
| 
moel@1
 | 
   142  | 
      get {
 | 
| 
moel@1
 | 
   143  | 
        return hardware.ToArray();
  | 
| 
moel@1
 | 
   144  | 
      }
  | 
| 
moel@1
 | 
   145  | 
    }
  | 
| 
moel@1
 | 
   146  | 
  | 
| 
moel@1
 | 
   147  | 
    private void AppendCpuidData(StringBuilder r, uint[,] data, uint offset) {
 | 
| 
moel@1
 | 
   148  | 
      for (int i = 0; i < data.GetLength(0); i++) {
 | 
| 
moel@1
 | 
   149  | 
        r.Append(" ");
 | 
| 
moel@1
 | 
   150  | 
        r.Append((i + offset).ToString("X8"));
 | 
| 
moel@1
 | 
   151  | 
        for (int j = 0; j < 4; j++) {
 | 
| 
moel@1
 | 
   152  | 
          r.Append("  ");
 | 
| 
moel@1
 | 
   153  | 
          r.Append(data[i, j].ToString("X8"));
 | 
| 
moel@1
 | 
   154  | 
        }
  | 
| 
moel@1
 | 
   155  | 
        r.AppendLine();
  | 
| 
moel@1
 | 
   156  | 
      }
  | 
| 
moel@1
 | 
   157  | 
    }
  | 
| 
moel@1
 | 
   158  | 
  | 
| 
moel@1
 | 
   159  | 
    public string GetReport() {
 | 
| 
moel@1
 | 
   160  | 
  | 
| 
moel@1
 | 
   161  | 
      StringBuilder r = new StringBuilder();
  | 
| 
moel@90
 | 
   162  | 
      
  | 
| 
moel@1
 | 
   163  | 
      r.AppendLine("CPUID");
 | 
| 
moel@1
 | 
   164  | 
      r.AppendLine();
  | 
| 
moel@1
 | 
   165  | 
  | 
| 
moel@90
 | 
   166  | 
      for (int i = 0; i < threads.Length; i++) {
 | 
| 
moel@1
 | 
   167  | 
  | 
| 
moel@90
 | 
   168  | 
        r.AppendLine("Processor " + i);
 | 
| 
moel@18
 | 
   169  | 
        r.AppendLine();
  | 
| 
moel@90
 | 
   170  | 
        r.AppendFormat("Processor Vendor: {0}{1}", threads[i][0][0].Vendor,
 | 
| 
moel@90
 | 
   171  | 
          Environment.NewLine);
  | 
| 
moel@90
 | 
   172  | 
        r.AppendFormat("Processor Brand: {0}{1}", threads[i][0][0].BrandString,
 | 
| 
moel@90
 | 
   173  | 
          Environment.NewLine);
  | 
| 
moel@90
 | 
   174  | 
        r.AppendFormat("Family: 0x{0}{1}", 
 | 
| 
moel@90
 | 
   175  | 
          threads[i][0][0].Family.ToString("X"), Environment.NewLine);
 | 
| 
moel@90
 | 
   176  | 
        r.AppendFormat("Model: 0x{0}{1}", 
 | 
| 
moel@90
 | 
   177  | 
          threads[i][0][0].Model.ToString("X"), Environment.NewLine);
 | 
| 
moel@90
 | 
   178  | 
        r.AppendFormat("Stepping: 0x{0}{1}", 
 | 
| 
moel@90
 | 
   179  | 
          threads[i][0][0].Stepping.ToString("X"), Environment.NewLine);
 | 
| 
moel@90
 | 
   180  | 
        r.AppendLine();
  | 
| 
moel@90
 | 
   181  | 
  | 
| 
moel@90
 | 
   182  | 
        r.AppendLine("CPUID Return Values");
 | 
| 
moel@90
 | 
   183  | 
        r.AppendLine();
  | 
| 
moel@90
 | 
   184  | 
        for (int j = 0; j < threads[i].Length; j++)
  | 
| 
moel@90
 | 
   185  | 
          for (int k = 0; k < threads[i][j].Length; k++) {
 | 
| 
moel@90
 | 
   186  | 
            r.AppendLine(" CPU Thread: " + threads[i][j][k].Thread);
 | 
| 
moel@90
 | 
   187  | 
            r.AppendLine(" APIC ID: " + threads[i][j][k].ApicId);
 | 
| 
moel@90
 | 
   188  | 
            r.AppendLine(" Processor ID: " + threads[i][j][k].ProcessorId);
 | 
| 
moel@90
 | 
   189  | 
            r.AppendLine(" Core ID: " + threads[i][j][k].CoreId);
 | 
| 
moel@90
 | 
   190  | 
            r.AppendLine(" Thread ID: " + threads[i][j][k].ThreadId);
 | 
| 
moel@90
 | 
   191  | 
            r.AppendLine();
  | 
| 
moel@90
 | 
   192  | 
            r.AppendLine(" Function  EAX       EBX       ECX       EDX");
 | 
| 
moel@90
 | 
   193  | 
            AppendCpuidData(r, threads[i][j][k].Data, CPUID.CPUID_0);
  | 
| 
moel@90
 | 
   194  | 
            AppendCpuidData(r, threads[i][j][k].ExtData, CPUID.CPUID_EXT);
  | 
| 
moel@90
 | 
   195  | 
            r.AppendLine();
  | 
| 
moel@90
 | 
   196  | 
          }
  | 
| 
moel@18
 | 
   197  | 
      }
  | 
| 
moel@90
 | 
   198  | 
      return r.ToString(); 
  | 
| 
moel@1
 | 
   199  | 
    }
  | 
| 
moel@1
 | 
   200  | 
  | 
| 
moel@1
 | 
   201  | 
    public void Close() { }
 | 
| 
moel@1
 | 
   202  | 
  }
  | 
| 
moel@1
 | 
   203  | 
}
  |