moel@1: /* moel@1: moel@1: Version: MPL 1.1/GPL 2.0/LGPL 2.1 moel@1: moel@1: The contents of this file are subject to the Mozilla Public License Version moel@1: 1.1 (the "License"); you may not use this file except in compliance with moel@1: the License. You may obtain a copy of the License at moel@1: moel@1: http://www.mozilla.org/MPL/ moel@1: moel@1: Software distributed under the License is distributed on an "AS IS" basis, moel@1: WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License moel@1: for the specific language governing rights and limitations under the License. moel@1: moel@1: The Original Code is the Open Hardware Monitor code. moel@1: moel@1: The Initial Developer of the Original Code is moel@1: Michael Möller . moel@1: Portions created by the Initial Developer are Copyright (C) 2009-2010 moel@1: the Initial Developer. All Rights Reserved. moel@1: moel@1: Contributor(s): moel@1: moel@1: Alternatively, the contents of this file may be used under the terms of moel@1: either the GNU General Public License Version 2 or later (the "GPL"), or moel@1: the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), moel@1: in which case the provisions of the GPL or the LGPL are applicable instead moel@1: of those above. If you wish to allow use of your version of this file only moel@1: under the terms of either the GPL or the LGPL, and not to allow others to moel@1: use your version of this file under the terms of the MPL, indicate your moel@1: decision by deleting the provisions above and replace them with the notice moel@1: and other provisions required by the GPL or the LGPL. If you do not delete moel@1: the provisions above, a recipient may use your version of this file under moel@1: the terms of any one of the MPL, the GPL or the LGPL. moel@1: moel@1: */ moel@1: moel@1: using System; moel@1: using System.Collections.Generic; moel@1: using System.Text; moel@1: moel@1: namespace OpenHardwareMonitor.Hardware.CPU { moel@1: moel@1: public class CPUGroup : IGroup { moel@1: private List hardware = new List(); moel@1: moel@1: private string cpuBrandString; moel@1: private string cpuVendor; moel@1: private uint[,] cpuidData; moel@1: private uint[,] cpuidExtData; moel@1: moel@1: private uint family; moel@1: private uint model; moel@1: private uint stepping; moel@1: moel@1: private static uint CPUID = 0; moel@1: private static uint CPUID_EXT = 0x80000000; moel@1: moel@1: public static void AppendRegister(StringBuilder b, uint value) { moel@1: b.Append((char)((value) & 0xff)); moel@1: b.Append((char)((value >> 8) & 0xff)); moel@1: b.Append((char)((value >> 16) & 0xff)); moel@1: b.Append((char)((value >> 24) & 0xff)); moel@1: } moel@1: moel@1: public CPUGroup() { moel@1: moel@1: if (!WinRing0.IsAvailable) moel@1: return; moel@1: moel@1: if (WinRing0.IsCpuid()) { moel@1: uint maxCPUID = 0; moel@1: uint maxCPUID_EXT = 0; moel@1: uint eax, ebx, ecx, edx; moel@1: moel@1: moel@1: if (WinRing0.Cpuid(CPUID, out eax, out ebx, out ecx, out edx)) { moel@1: maxCPUID = eax; moel@1: StringBuilder vendorBuilder = new StringBuilder(); moel@1: AppendRegister(vendorBuilder, ebx); moel@1: AppendRegister(vendorBuilder, edx); moel@1: AppendRegister(vendorBuilder, ecx); moel@1: cpuVendor = vendorBuilder.ToString(); moel@1: moel@1: eax = ebx = ecx = edx = 0; moel@1: if (WinRing0.Cpuid(CPUID_EXT, out eax, out ebx, out ecx, out edx)) { moel@1: maxCPUID_EXT = eax - CPUID_EXT; moel@1: } moel@1: } moel@1: if (maxCPUID == 0 || maxCPUID_EXT == 0) moel@1: return; moel@1: moel@1: cpuidData = new uint[maxCPUID + 1, 4]; moel@1: for (uint i = 0; i < (maxCPUID + 1); i++) moel@1: WinRing0.Cpuid(CPUID + i, out cpuidData[i, 0], out cpuidData[i, 1], moel@1: out cpuidData[i, 2], out cpuidData[i, 3]); moel@1: moel@1: cpuidExtData = new uint[maxCPUID_EXT + 1, 4]; moel@1: for (uint i = 0; i < (maxCPUID_EXT + 1); i++) moel@1: WinRing0.Cpuid(CPUID_EXT + i, out cpuidExtData[i, 0], moel@1: out cpuidExtData[i, 1], out cpuidExtData[i, 2], moel@1: out cpuidExtData[i, 3]); moel@1: moel@1: StringBuilder nameBuilder = new StringBuilder(); moel@1: for (uint i = 2; i <= 4; i++) { moel@1: if (WinRing0.Cpuid(CPUID_EXT + i, out eax, out ebx, out ecx, out edx)) moel@1: { moel@1: AppendRegister(nameBuilder, eax); moel@1: AppendRegister(nameBuilder, ebx); moel@1: AppendRegister(nameBuilder, ecx); moel@1: AppendRegister(nameBuilder, edx); moel@1: } moel@1: } moel@18: cpuBrandString = nameBuilder.ToString().Trim('\0'); moel@1: nameBuilder.Replace("(R)", " "); moel@1: nameBuilder.Replace("(TM)", " "); moel@1: nameBuilder.Replace("(tm)", " "); moel@1: nameBuilder.Replace("CPU", ""); moel@1: for (int i = 0; i < 10; i++) nameBuilder.Replace(" ", " "); moel@1: string name = nameBuilder.ToString(); moel@1: if (name.Contains("@")) moel@1: name = name.Remove(name.LastIndexOf('@')); moel@1: name = name.Trim(); moel@1: moel@1: this.family = ((cpuidData[1, 0] & 0x0FF00000) >> 20) + moel@1: ((cpuidData[1, 0] & 0x0F00) >> 8); moel@1: this.model = ((cpuidData[1, 0] & 0x0F0000) >> 12) + moel@1: ((cpuidData[1, 0] & 0xF0) >> 4); moel@1: this.stepping = (cpuidData[1, 0] & 0x0F); moel@1: moel@1: switch (cpuVendor) { moel@1: case "GenuineIntel": moel@1: // check if processor supports a digital thermal sensor moel@1: if (maxCPUID >= 6 && (cpuidData[6, 0] & 1) != 0) moel@1: hardware.Add(new IntelCPU(name, family, model, stepping, moel@1: cpuidData, cpuidExtData)); moel@1: break; moel@1: case "AuthenticAMD": moel@1: // check if processor supports a digital thermal sensor moel@1: if (maxCPUID_EXT >= 7 && (cpuidExtData[7, 3] & 1) != 0) { moel@1: switch (family) { moel@14: case 0x0F: moel@14: hardware.Add(new AMD0FCPU(name, family, model, stepping, moel@14: cpuidData, cpuidExtData)); moel@14: break; moel@1: case 0x10: moel@1: hardware.Add(new AMD10CPU(name, family, model, stepping, moel@1: cpuidData, cpuidExtData)); moel@1: break; moel@1: default: moel@1: break; moel@1: } moel@1: } moel@1: break; moel@1: default: moel@1: break; moel@1: } moel@1: } moel@1: } moel@1: moel@1: public IHardware[] Hardware { moel@1: get { moel@1: return hardware.ToArray(); moel@1: } moel@1: } moel@1: moel@1: private void AppendCpuidData(StringBuilder r, uint[,] data, uint offset) { moel@1: for (int i = 0; i < data.GetLength(0); i++) { moel@1: r.Append(" "); moel@1: r.Append((i + offset).ToString("X8")); moel@1: for (int j = 0; j < 4; j++) { moel@1: r.Append(" "); moel@1: r.Append(data[i, j].ToString("X8")); moel@1: } moel@1: r.AppendLine(); moel@1: } moel@1: } moel@1: moel@1: public string GetReport() { moel@1: moel@1: StringBuilder r = new StringBuilder(); moel@1: moel@1: r.AppendLine("CPUID"); moel@1: r.AppendLine(); moel@1: r.AppendFormat("Processor Vendor: {0}{1}", cpuVendor, moel@1: Environment.NewLine); moel@1: r.AppendFormat("Processor Brand: {0}{1}", cpuBrandString, moel@1: Environment.NewLine); moel@1: r.AppendFormat("Family: 0x{0}{1}", family.ToString("X"), moel@1: Environment.NewLine); moel@1: r.AppendFormat("Model: 0x{0}{1}", model.ToString("X"), moel@1: Environment.NewLine); moel@1: r.AppendFormat("Stepping: 0x{0}{1}", stepping.ToString("X"), moel@1: Environment.NewLine); moel@1: r.AppendLine(); moel@1: moel@1: r.AppendLine("CPUID Return Values"); moel@1: r.AppendLine(); moel@1: moel@18: if (cpuidData != null) { moel@18: r.AppendLine(" Function EAX EBX ECX EDX"); moel@18: AppendCpuidData(r, cpuidData, CPUID); moel@18: AppendCpuidData(r, cpuidExtData, CPUID_EXT); moel@18: r.AppendLine(); moel@18: } moel@1: moel@1: return r.ToString(); moel@1: } moel@1: moel@1: public void Close() { } moel@1: } moel@1: }