Fixed some Code Analysis warnings.
     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;
 
    40 using System.Globalization;
 
    43 namespace OpenHardwareMonitor.Hardware.Nvidia {
 
    44   internal class NvidiaGPU : Hardware, IHardware {
 
    47     private int adapterIndex;
 
    48     private NvPhysicalGpuHandle handle;
 
    49     private NvDisplayHandle? displayHandle;
 
    51     private Sensor[] temperatures;
 
    52     private Sensor fan = null;
 
    53     private Sensor[] clocks;
 
    54     private Sensor[] loads;
 
    55     private Sensor control;
 
    56     private Sensor memoryLoad;
 
    58     public NvidiaGPU(int adapterIndex, NvPhysicalGpuHandle handle, 
 
    59       NvDisplayHandle? displayHandle, ISettings settings) 
 
    62       if (NVAPI.NvAPI_GPU_GetFullName(handle, out gpuName) == NvStatus.OK) {
 
    63         this.name = "NVIDIA " + gpuName.Trim();
 
    67       this.adapterIndex = adapterIndex;
 
    69       this.displayHandle = displayHandle;
 
    71       NvGPUThermalSettings thermalSettings = GetThermalSettings();
 
    72       temperatures = new Sensor[thermalSettings.Count];
 
    73       for (int i = 0; i < temperatures.Length; i++) {
 
    74         NvSensor sensor = thermalSettings.Sensor[i];
 
    76         switch (sensor.Target) {
 
    77           case NvThermalTarget.BOARD: name = "GPU Board"; break;
 
    78           case NvThermalTarget.GPU: name = "GPU Core"; break;
 
    79           case NvThermalTarget.MEMORY: name = "GPU Memory"; break;
 
    80           case NvThermalTarget.POWER_SUPPLY: name = "GPU Power Supply"; break;
 
    81           case NvThermalTarget.UNKNOWN: name = "GPU Unknown"; break;
 
    82           default: name = "GPU"; break;
 
    84         temperatures[i] = new Sensor(name, i, SensorType.Temperature, this,
 
    85           new ParameterDescription[0], settings);
 
    86         ActivateSensor(temperatures[i]);
 
    90       if (NVAPI.NvAPI_GPU_GetTachReading != null &&
 
    91         NVAPI.NvAPI_GPU_GetTachReading(handle, out value) == NvStatus.OK) {
 
    93           fan = new Sensor("GPU", 0, SensorType.Fan, this, settings);
 
    98       clocks = new Sensor[3];
 
    99       clocks[0] = new Sensor("GPU Core", 0, SensorType.Clock, this, settings);
 
   100       clocks[1] = new Sensor("GPU Memory", 1, SensorType.Clock, this, settings);
 
   101       clocks[2] = new Sensor("GPU Shader", 2, SensorType.Clock, this, settings);
 
   102       for (int i = 0; i < clocks.Length; i++)
 
   103         ActivateSensor(clocks[i]);
 
   105       loads = new Sensor[3];
 
   106       loads[0] = new Sensor("GPU Core", 0, SensorType.Load, this, settings);
 
   107       loads[1] = new Sensor("GPU Memory Controller", 1, SensorType.Load, this, settings);
 
   108       loads[2] = new Sensor("GPU Video Engine", 2, SensorType.Load, this, settings);
 
   109       memoryLoad = new Sensor("GPU Memory", 3, SensorType.Load, this, settings);
 
   111       control = new Sensor("GPU Fan", 0, SensorType.Control, this, settings);
 
   114     public override string Name {
 
   118     public override Identifier Identifier {
 
   120         return new Identifier("nvidiagpu", 
 
   121           adapterIndex.ToString(CultureInfo.InvariantCulture)); 
 
   125     public override HardwareType HardwareType {
 
   126       get { return HardwareType.GPU; }
 
   129     private NvGPUThermalSettings GetThermalSettings() {
 
   130       NvGPUThermalSettings settings = new NvGPUThermalSettings();
 
   131       settings.Version = NVAPI.GPU_THERMAL_SETTINGS_VER;
 
   132       settings.Count = NVAPI.MAX_THERMAL_SENSORS_PER_GPU;
 
   133       settings.Sensor = new NvSensor[NVAPI.MAX_THERMAL_SENSORS_PER_GPU];
 
   134       if (NVAPI.NvAPI_GPU_GetThermalSettings != null &&
 
   135         NVAPI.NvAPI_GPU_GetThermalSettings(handle, (int)NvThermalTarget.ALL,
 
   136         ref settings) != NvStatus.OK) {
 
   142     private uint[] GetClocks() {
 
   143       NvClocks allClocks = new NvClocks();
 
   144       allClocks.Version = NVAPI.GPU_CLOCKS_VER;
 
   145       allClocks.Clock = new uint[NVAPI.MAX_CLOCKS_PER_GPU];
 
   146       if (NVAPI.NvAPI_GPU_GetAllClocks != null &&
 
   147         NVAPI.NvAPI_GPU_GetAllClocks(handle, ref allClocks) == NvStatus.OK) {
 
   148         return allClocks.Clock;
 
   153     public override void Update() {
 
   154       NvGPUThermalSettings settings = GetThermalSettings();
 
   155       foreach (Sensor sensor in temperatures) 
 
   156         sensor.Value = settings.Sensor[sensor.Index].CurrentTemp;
 
   160         NVAPI.NvAPI_GPU_GetTachReading(handle, out value);
 
   164       uint[] values = GetClocks();
 
   165       if (values != null) {
 
   166         clocks[0].Value = 0.001f * values[0];
 
   167         clocks[1].Value = 0.001f * values[8];
 
   168         clocks[2].Value = 0.001f * values[14];
 
   169         if (values[30] != 0) {
 
   170           clocks[0].Value = 0.0005f * values[30];
 
   171           clocks[2].Value = 0.001f * values[30];
 
   175       NvPStates states = new NvPStates();
 
   176       states.Version = NVAPI.GPU_PSTATES_VER;
 
   177       states.PStates = new NvPState[NVAPI.MAX_PSTATES_PER_GPU];
 
   178       if (NVAPI.NvAPI_GPU_GetPStates != null && 
 
   179         NVAPI.NvAPI_GPU_GetPStates(handle, ref states) == NvStatus.OK) {
 
   180         for (int i = 0; i < 3; i++)
 
   181           if (states.PStates[i].Present) {
 
   182             loads[i].Value = states.PStates[i].Percentage;
 
   183             ActivateSensor(loads[i]);
 
   186         NvUsages usages = new NvUsages();
 
   187         usages.Version = NVAPI.GPU_USAGES_VER;
 
   188         usages.Usage = new uint[NVAPI.MAX_USAGES_PER_GPU];
 
   189         if (NVAPI.NvAPI_GPU_GetUsages != null &&
 
   190           NVAPI.NvAPI_GPU_GetUsages(handle, ref usages) == NvStatus.OK) {
 
   191           loads[0].Value = usages.Usage[2];
 
   192           loads[1].Value = usages.Usage[6];
 
   193           loads[2].Value = usages.Usage[10];
 
   194           for (int i = 0; i < 3; i++)
 
   195             ActivateSensor(loads[i]);
 
   199       NvGPUCoolerSettings coolerSettings = new NvGPUCoolerSettings();
 
   200       coolerSettings.Version = NVAPI.GPU_COOLER_SETTINGS_VER;
 
   201       coolerSettings.Cooler = new NvCooler[NVAPI.MAX_COOLER_PER_GPU];
 
   202       if (NVAPI.NvAPI_GPU_GetCoolerSettings != null && 
 
   203         NVAPI.NvAPI_GPU_GetCoolerSettings(handle, 0, ref coolerSettings) ==
 
   204         NvStatus.OK && coolerSettings.Count > 0) {
 
   205         control.Value = coolerSettings.Cooler[0].CurrentLevel;
 
   206         ActivateSensor(control);
 
   209       NvMemoryInfo memoryInfo = new NvMemoryInfo();
 
   210       memoryInfo.Version = NVAPI.GPU_MEMORY_INFO_VER;
 
   211       memoryInfo.Values = new uint[NVAPI.MAX_MEMORY_VALUES_PER_GPU];
 
   212       if (NVAPI.NvAPI_GPU_GetMemoryInfo != null && displayHandle.HasValue &&
 
   213         NVAPI.NvAPI_GPU_GetMemoryInfo(displayHandle.Value, ref memoryInfo) == 
 
   216         uint totalMemory = memoryInfo.Values[0];
 
   217         uint freeMemory = memoryInfo.Values[4];
 
   218         float usedMemory = Math.Max(totalMemory - freeMemory, 0);
 
   219         memoryLoad.Value = 100f * usedMemory / totalMemory;
 
   220         ActivateSensor(memoryLoad);
 
   224     public override string GetReport() {
 
   225       StringBuilder r = new StringBuilder();
 
   227       r.AppendLine("Nvidia GPU");
 
   230       r.AppendFormat("Name: {0}{1}", name, Environment.NewLine);
 
   231       r.AppendFormat("Index: {0}{1}", adapterIndex, Environment.NewLine);
 
   233       if (displayHandle.HasValue && NVAPI.NvAPI_GetDisplayDriverVersion != null) 
 
   235         NvDisplayDriverVersion driverVersion = new NvDisplayDriverVersion();
 
   236         driverVersion.Version = NVAPI.DISPLAY_DRIVER_VERSION_VER;
 
   237         if (NVAPI.NvAPI_GetDisplayDriverVersion(displayHandle.Value,
 
   238           ref driverVersion) == NvStatus.OK) {
 
   239           r.Append("Driver Version: ");
 
   240           r.Append(driverVersion.DriverVersion / 100);
 
   242           r.Append((driverVersion.DriverVersion % 100).ToString("00", 
 
   243             CultureInfo.InvariantCulture));
 
   245           r.Append("Driver Branch: ");
 
   246           r.AppendLine(driverVersion.BuildBranch);
 
   251       if (NVAPI.NvAPI_GPU_GetThermalSettings != null) {
 
   252         NvGPUThermalSettings settings = new NvGPUThermalSettings();
 
   253         settings.Version = NVAPI.GPU_THERMAL_SETTINGS_VER;
 
   254         settings.Count = NVAPI.MAX_THERMAL_SENSORS_PER_GPU;
 
   255         settings.Sensor = new NvSensor[NVAPI.MAX_THERMAL_SENSORS_PER_GPU];
 
   257         NvStatus status = NVAPI.NvAPI_GPU_GetThermalSettings(handle,
 
   258           (int)NvThermalTarget.ALL, ref settings);
 
   260         r.AppendLine("Thermal Settings");
 
   262         if (status == NvStatus.OK) {
 
   263           for (int i = 0; i < settings.Count; i++) {
 
   264             r.AppendFormat(" Sensor[{0}].Controller: {1}{2}", i,
 
   265               settings.Sensor[i].Controller, Environment.NewLine);
 
   266             r.AppendFormat(" Sensor[{0}].DefaultMinTemp: {1}{2}", i,
 
   267               settings.Sensor[i].DefaultMinTemp, Environment.NewLine);
 
   268             r.AppendFormat(" Sensor[{0}].DefaultMaxTemp: {1}{2}", i,
 
   269               settings.Sensor[i].DefaultMaxTemp, Environment.NewLine);
 
   270             r.AppendFormat(" Sensor[{0}].CurrentTemp: {1}{2}", i,
 
   271               settings.Sensor[i].CurrentTemp, Environment.NewLine);
 
   272             r.AppendFormat(" Sensor[{0}].Target: {1}{2}", i,
 
   273               settings.Sensor[i].Target, Environment.NewLine);
 
   276           r.Append(" Status: ");
 
   277           r.AppendLine(status.ToString());
 
   282       if (NVAPI.NvAPI_GPU_GetAllClocks != null) {
 
   283         NvClocks allClocks = new NvClocks();
 
   284         allClocks.Version = NVAPI.GPU_CLOCKS_VER;
 
   285         allClocks.Clock = new uint[NVAPI.MAX_CLOCKS_PER_GPU];
 
   286         NvStatus status = NVAPI.NvAPI_GPU_GetAllClocks(handle, ref allClocks);
 
   288         r.AppendLine("Clocks");
 
   290         if (status == NvStatus.OK) {
 
   291           for (int i = 0; i < allClocks.Clock.Length; i++)
 
   292             if (allClocks.Clock[i] > 0) {
 
   293               r.AppendFormat(" Clock[{0}]: {1}{2}", i, allClocks.Clock[i],
 
   294                 Environment.NewLine);
 
   297           r.Append(" Status: ");
 
   298           r.AppendLine(status.ToString());
 
   303       if (NVAPI.NvAPI_GPU_GetTachReading != null) {
 
   305         NvStatus status = NVAPI.NvAPI_GPU_GetTachReading(handle, out tachValue);
 
   307         r.AppendLine("Tachometer");
 
   309         if (status == NvStatus.OK) {
 
   310           r.AppendFormat(" Value: {0}{1}", tachValue, Environment.NewLine);
 
   312           r.Append(" Status: ");
 
   313           r.AppendLine(status.ToString());
 
   318       if (NVAPI.NvAPI_GPU_GetPStates != null) {
 
   319         NvPStates states = new NvPStates();
 
   320         states.Version = NVAPI.GPU_PSTATES_VER;
 
   321         states.PStates = new NvPState[NVAPI.MAX_PSTATES_PER_GPU];
 
   322         NvStatus status = NVAPI.NvAPI_GPU_GetPStates(handle, ref states);
 
   324         r.AppendLine("P-States");
 
   326         if (status == NvStatus.OK) {
 
   327           for (int i = 0; i < states.PStates.Length; i++)
 
   328             if (states.PStates[i].Present)
 
   329               r.AppendFormat(" Percentage[{0}]: {1}{2}", i,
 
   330                 states.PStates[i].Percentage, Environment.NewLine);
 
   332           r.Append(" Status: ");
 
   333           r.AppendLine(status.ToString());
 
   338       if (NVAPI.NvAPI_GPU_GetUsages != null) {
 
   339         NvUsages usages = new NvUsages();
 
   340         usages.Version = NVAPI.GPU_USAGES_VER;
 
   341         usages.Usage = new uint[NVAPI.MAX_USAGES_PER_GPU];
 
   342         NvStatus status = NVAPI.NvAPI_GPU_GetUsages(handle, ref usages);
 
   344         r.AppendLine("Usages");
 
   346         if (status == NvStatus.OK) {
 
   347           for (int i = 0; i < usages.Usage.Length; i++)
 
   348             if (usages.Usage[i] > 0)
 
   349               r.AppendFormat(" Usage[{0}]: {1}{2}", i,
 
   350                 usages.Usage[i], Environment.NewLine);
 
   352           r.Append(" Status: ");
 
   353           r.AppendLine(status.ToString());
 
   358       if (NVAPI.NvAPI_GPU_GetCoolerSettings != null) {
 
   359         NvGPUCoolerSettings settings = new NvGPUCoolerSettings();
 
   360         settings.Version = NVAPI.GPU_COOLER_SETTINGS_VER;
 
   361         settings.Cooler = new NvCooler[NVAPI.MAX_COOLER_PER_GPU];
 
   363           NVAPI.NvAPI_GPU_GetCoolerSettings(handle, 0, ref settings);
 
   365         r.AppendLine("Cooler Settings");
 
   367         if (status == NvStatus.OK) {
 
   368           for (int i = 0; i < settings.Count; i++) {
 
   369             r.AppendFormat(" Cooler[{0}].Type: {1}{2}", i,
 
   370               settings.Cooler[i].Type, Environment.NewLine);
 
   371             r.AppendFormat(" Cooler[{0}].Controller: {1}{2}", i,
 
   372               settings.Cooler[i].Controller, Environment.NewLine);
 
   373             r.AppendFormat(" Cooler[{0}].DefaultMin: {1}{2}", i,
 
   374               settings.Cooler[i].DefaultMin, Environment.NewLine);
 
   375             r.AppendFormat(" Cooler[{0}].DefaultMax: {1}{2}", i,
 
   376               settings.Cooler[i].DefaultMax, Environment.NewLine);
 
   377             r.AppendFormat(" Cooler[{0}].CurrentMin: {1}{2}", i,
 
   378               settings.Cooler[i].CurrentMin, Environment.NewLine);
 
   379             r.AppendFormat(" Cooler[{0}].CurrentMax: {1}{2}", i,
 
   380               settings.Cooler[i].CurrentMax, Environment.NewLine);
 
   381             r.AppendFormat(" Cooler[{0}].CurrentLevel: {1}{2}", i,
 
   382               settings.Cooler[i].CurrentLevel, Environment.NewLine);
 
   383             r.AppendFormat(" Cooler[{0}].DefaultPolicy: {1}{2}", i,
 
   384               settings.Cooler[i].DefaultPolicy, Environment.NewLine);
 
   385             r.AppendFormat(" Cooler[{0}].CurrentPolicy: {1}{2}", i,
 
   386               settings.Cooler[i].CurrentPolicy, Environment.NewLine);
 
   387             r.AppendFormat(" Cooler[{0}].Target: {1}{2}", i,
 
   388               settings.Cooler[i].Target, Environment.NewLine);
 
   389             r.AppendFormat(" Cooler[{0}].ControlType: {1}{2}", i,
 
   390               settings.Cooler[i].ControlType, Environment.NewLine);
 
   391             r.AppendFormat(" Cooler[{0}].Active: {1}{2}", i,
 
   392               settings.Cooler[i].Active, Environment.NewLine);
 
   395           r.Append(" Status: ");
 
   396           r.AppendLine(status.ToString());
 
   401       if (NVAPI.NvAPI_GPU_GetMemoryInfo != null && displayHandle.HasValue) {
 
   402         NvMemoryInfo memoryInfo = new NvMemoryInfo();
 
   403         memoryInfo.Version = NVAPI.GPU_MEMORY_INFO_VER;
 
   404         memoryInfo.Values = new uint[NVAPI.MAX_MEMORY_VALUES_PER_GPU];
 
   405         NvStatus status = NVAPI.NvAPI_GPU_GetMemoryInfo(displayHandle.Value, 
 
   408         r.AppendLine("Memory Info");
 
   410         if (status == NvStatus.OK) {
 
   411           for (int i = 0; i < memoryInfo.Values.Length; i++)
 
   412             r.AppendFormat(" Value[{0}]: {1}{2}", i,
 
   413                 memoryInfo.Values[i], Environment.NewLine);
 
   415           r.Append(" Status: ");
 
   416           r.AppendLine(status.ToString());