Improved Winbond temperature reading. Temperatures create by adding PECI Agent values (delta to TCC Activation Temperature) to a (possibly uncalibrated) TBase are not read. Direct reading temperatures from sensor report register if available. Added lower bound for temperatures on Winbond chips. Nvidia GPUs are now displayed even if they do not have any sensors.
3 Version: MPL 1.1/GPL 2.0/LGPL 2.1
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
9 http://www.mozilla.org/MPL/
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.
15 The Original Code is the Open Hardware Monitor code.
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.
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.
39 using System.Collections.Generic;
42 namespace OpenHardwareMonitor.Hardware.CPU {
44 public class CPUGroup : IGroup {
45 private List<IHardware> hardware = new List<IHardware>();
47 private string cpuBrandString;
48 private string cpuVendor;
49 private uint[,] cpuidData;
50 private uint[,] cpuidExtData;
54 private uint stepping;
56 private static uint CPUID = 0;
57 private static uint CPUID_EXT = 0x80000000;
59 public static void AppendRegister(StringBuilder b, uint value) {
60 b.Append((char)((value) & 0xff));
61 b.Append((char)((value >> 8) & 0xff));
62 b.Append((char)((value >> 16) & 0xff));
63 b.Append((char)((value >> 24) & 0xff));
68 if (!WinRing0.IsAvailable)
71 if (WinRing0.IsCpuid()) {
73 uint maxCPUID_EXT = 0;
74 uint eax, ebx, ecx, edx;
77 if (WinRing0.Cpuid(CPUID, out eax, out ebx, out ecx, out edx)) {
79 StringBuilder vendorBuilder = new StringBuilder();
80 AppendRegister(vendorBuilder, ebx);
81 AppendRegister(vendorBuilder, edx);
82 AppendRegister(vendorBuilder, ecx);
83 cpuVendor = vendorBuilder.ToString();
85 eax = ebx = ecx = edx = 0;
86 if (WinRing0.Cpuid(CPUID_EXT, out eax, out ebx, out ecx, out edx)) {
87 maxCPUID_EXT = eax - CPUID_EXT;
90 if (maxCPUID == 0 || maxCPUID_EXT == 0)
93 cpuidData = new uint[maxCPUID + 1, 4];
94 for (uint i = 0; i < (maxCPUID + 1); i++)
95 WinRing0.Cpuid(CPUID + i, out cpuidData[i, 0], out cpuidData[i, 1],
96 out cpuidData[i, 2], out cpuidData[i, 3]);
98 cpuidExtData = new uint[maxCPUID_EXT + 1, 4];
99 for (uint i = 0; i < (maxCPUID_EXT + 1); i++)
100 WinRing0.Cpuid(CPUID_EXT + i, out cpuidExtData[i, 0],
101 out cpuidExtData[i, 1], out cpuidExtData[i, 2],
102 out cpuidExtData[i, 3]);
104 StringBuilder nameBuilder = new StringBuilder();
105 for (uint i = 2; i <= 4; i++) {
106 if (WinRing0.Cpuid(CPUID_EXT + i, out eax, out ebx, out ecx, out edx))
108 AppendRegister(nameBuilder, eax);
109 AppendRegister(nameBuilder, ebx);
110 AppendRegister(nameBuilder, ecx);
111 AppendRegister(nameBuilder, edx);
114 nameBuilder.Replace('\0', ' ');
115 cpuBrandString = nameBuilder.ToString().Trim();
116 nameBuilder.Replace("(R)", " ");
117 nameBuilder.Replace("(TM)", " ");
118 nameBuilder.Replace("(tm)", " ");
119 nameBuilder.Replace("CPU", "");
120 for (int i = 0; i < 10; i++) nameBuilder.Replace(" ", " ");
121 string name = nameBuilder.ToString();
122 if (name.Contains("@"))
123 name = name.Remove(name.LastIndexOf('@'));
126 this.family = ((cpuidData[1, 0] & 0x0FF00000) >> 20) +
127 ((cpuidData[1, 0] & 0x0F00) >> 8);
128 this.model = ((cpuidData[1, 0] & 0x0F0000) >> 12) +
129 ((cpuidData[1, 0] & 0xF0) >> 4);
130 this.stepping = (cpuidData[1, 0] & 0x0F);
134 hardware.Add(new IntelCPU(name, family, model, stepping,
135 cpuidData, cpuidExtData));
138 // check if processor supports a digital thermal sensor
139 if (maxCPUID_EXT >= 7 && (cpuidExtData[7, 3] & 1) != 0) {
142 hardware.Add(new AMD0FCPU(name, family, model, stepping,
143 cpuidData, cpuidExtData));
146 hardware.Add(new AMD10CPU(name, family, model, stepping,
147 cpuidData, cpuidExtData));
160 public IHardware[] Hardware {
162 return hardware.ToArray();
166 private void AppendCpuidData(StringBuilder r, uint[,] data, uint offset) {
167 for (int i = 0; i < data.GetLength(0); i++) {
169 r.Append((i + offset).ToString("X8"));
170 for (int j = 0; j < 4; j++) {
172 r.Append(data[i, j].ToString("X8"));
178 public string GetReport() {
180 StringBuilder r = new StringBuilder();
182 r.AppendLine("CPUID");
184 r.AppendFormat("Processor Vendor: {0}{1}", cpuVendor,
185 Environment.NewLine);
186 r.AppendFormat("Processor Brand: {0}{1}", cpuBrandString,
187 Environment.NewLine);
188 r.AppendFormat("Family: 0x{0}{1}", family.ToString("X"),
189 Environment.NewLine);
190 r.AppendFormat("Model: 0x{0}{1}", model.ToString("X"),
191 Environment.NewLine);
192 r.AppendFormat("Stepping: 0x{0}{1}", stepping.ToString("X"),
193 Environment.NewLine);
196 r.AppendLine("CPUID Return Values");
199 if (cpuidData != null) {
200 r.AppendLine(" Function EAX EBX ECX EDX");
201 AppendCpuidData(r, cpuidData, CPUID);
202 AppendCpuidData(r, cpuidExtData, CPUID_EXT);
209 public void Close() { }