Hardware/Nvidia/NvidiaGPU.cs
author moel.mich
Sat, 31 Dec 2011 17:31:04 +0000
changeset 324 c6ee430d6995
parent 275 35788ddd1825
child 334 013e148e8f12
permissions -rw-r--r--
Modified and extended version of the patch v4 by Roland Reinl (see Issue 256). Main differences to the original patch: DeviceIoControl refactorings removed, SmartAttribute is now descriptive only and does not hold any state, report is written as one 80 columns table, sensors are created only for meaningful values and without duplicates (remaining life, temperatures, host writes and reads). Also the current implementation should really preserve all the functionality of the old system. Additionally there is now a simple SMART devices emulation class (DebugSmart) that can be used in place of WindowsSmart for testing with reported data.
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@275
    19
  Portions created by the Initial Developer are Copyright (C) 2009-2011
moel@1
    20
  the Initial Developer. All Rights Reserved.
moel@1
    21
moel@1
    22
  Contributor(s):
moel@309
    23
  Christian Vallières
moel@1
    24
moel@1
    25
  Alternatively, the contents of this file may be used under the terms of
moel@1
    26
  either the GNU General Public License Version 2 or later (the "GPL"), or
moel@1
    27
  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
moel@1
    28
  in which case the provisions of the GPL or the LGPL are applicable instead
moel@1
    29
  of those above. If you wish to allow use of your version of this file only
moel@1
    30
  under the terms of either the GPL or the LGPL, and not to allow others to
moel@1
    31
  use your version of this file under the terms of the MPL, indicate your
moel@1
    32
  decision by deleting the provisions above and replace them with the notice
moel@1
    33
  and other provisions required by the GPL or the LGPL. If you do not delete
moel@1
    34
  the provisions above, a recipient may use your version of this file under
moel@1
    35
  the terms of any one of the MPL, the GPL or the LGPL.
moel@1
    36
 
moel@1
    37
*/
moel@1
    38
moel@1
    39
using System;
moel@166
    40
using System.Globalization;
moel@140
    41
using System.Text;
moel@1
    42
moel@1
    43
namespace OpenHardwareMonitor.Hardware.Nvidia {
moel@195
    44
  internal class NvidiaGPU : Hardware {
moel@1
    45
moel@195
    46
    private readonly int adapterIndex;
moel@195
    47
    private readonly NvPhysicalGpuHandle handle;
moel@195
    48
    private readonly NvDisplayHandle? displayHandle;
moel@1
    49
moel@195
    50
    private readonly Sensor[] temperatures;
moel@195
    51
    private readonly Sensor fan;
moel@195
    52
    private readonly Sensor[] clocks;
moel@195
    53
    private readonly Sensor[] loads;
moel@195
    54
    private readonly Sensor control;
moel@195
    55
    private readonly Sensor memoryLoad;
moel@309
    56
    private readonly Control fanControl;
moel@38
    57
moel@309
    58
    private bool restoreDefaultFanSpeedRequired;
moel@309
    59
    private NvLevel initialFanSpeedValue;
moel@309
    60
moel@309
    61
    public NvidiaGPU(int adapterIndex, NvPhysicalGpuHandle handle,
moel@309
    62
      NvDisplayHandle? displayHandle, ISettings settings)
moel@309
    63
      : base(GetName(handle), new Identifier("nvidiagpu",
moel@309
    64
          adapterIndex.ToString(CultureInfo.InvariantCulture)), settings) {
moel@56
    65
      this.adapterIndex = adapterIndex;
moel@56
    66
      this.handle = handle;
moel@140
    67
      this.displayHandle = displayHandle;
moel@1
    68
moel@165
    69
      NvGPUThermalSettings thermalSettings = GetThermalSettings();
moel@165
    70
      temperatures = new Sensor[thermalSettings.Count];
moel@56
    71
      for (int i = 0; i < temperatures.Length; i++) {
moel@165
    72
        NvSensor sensor = thermalSettings.Sensor[i];
moel@56
    73
        string name;
moel@56
    74
        switch (sensor.Target) {
moel@56
    75
          case NvThermalTarget.BOARD: name = "GPU Board"; break;
moel@56
    76
          case NvThermalTarget.GPU: name = "GPU Core"; break;
moel@56
    77
          case NvThermalTarget.MEMORY: name = "GPU Memory"; break;
moel@56
    78
          case NvThermalTarget.POWER_SUPPLY: name = "GPU Power Supply"; break;
moel@56
    79
          case NvThermalTarget.UNKNOWN: name = "GPU Unknown"; break;
moel@56
    80
          default: name = "GPU"; break;
moel@38
    81
        }
moel@165
    82
        temperatures[i] = new Sensor(name, i, SensorType.Temperature, this,
moel@165
    83
          new ParameterDescription[0], settings);
moel@56
    84
        ActivateSensor(temperatures[i]);
moel@56
    85
      }
moel@1
    86
moel@56
    87
      int value;
moel@56
    88
      if (NVAPI.NvAPI_GPU_GetTachReading != null &&
moel@56
    89
        NVAPI.NvAPI_GPU_GetTachReading(handle, out value) == NvStatus.OK) {
moel@56
    90
        if (value > 0) {
moel@165
    91
          fan = new Sensor("GPU", 0, SensorType.Fan, this, settings);
moel@56
    92
          ActivateSensor(fan);
moel@1
    93
        }
moel@1
    94
      }
moel@140
    95
moel@140
    96
      clocks = new Sensor[3];
moel@165
    97
      clocks[0] = new Sensor("GPU Core", 0, SensorType.Clock, this, settings);
moel@165
    98
      clocks[1] = new Sensor("GPU Memory", 1, SensorType.Clock, this, settings);
moel@165
    99
      clocks[2] = new Sensor("GPU Shader", 2, SensorType.Clock, this, settings);
moel@140
   100
      for (int i = 0; i < clocks.Length; i++)
moel@140
   101
        ActivateSensor(clocks[i]);
moel@140
   102
moel@140
   103
      loads = new Sensor[3];
moel@165
   104
      loads[0] = new Sensor("GPU Core", 0, SensorType.Load, this, settings);
moel@165
   105
      loads[1] = new Sensor("GPU Memory Controller", 1, SensorType.Load, this, settings);
moel@165
   106
      loads[2] = new Sensor("GPU Video Engine", 2, SensorType.Load, this, settings);
moel@165
   107
      memoryLoad = new Sensor("GPU Memory", 3, SensorType.Load, this, settings);
moel@140
   108
moel@165
   109
      control = new Sensor("GPU Fan", 0, SensorType.Control, this, settings);
moel@309
   110
moel@309
   111
      NvGPUCoolerSettings coolerSettings = GetCoolerSettings();
moel@309
   112
      if (coolerSettings.Count > 0) {
moel@309
   113
        fanControl = new Control(control, settings,
moel@309
   114
          coolerSettings.Cooler[0].DefaultMin, 
moel@309
   115
          coolerSettings.Cooler[0].DefaultMax);
moel@309
   116
        fanControl.ControlModeChanged += ControlModeChanged;
moel@309
   117
        fanControl.SoftwareControlValueChanged += SoftwareControlValueChanged;
moel@309
   118
        ControlModeChanged(fanControl);
moel@309
   119
        control.Control = fanControl;
moel@309
   120
      }
moel@309
   121
      Update();
moel@1
   122
    }
moel@1
   123
moel@275
   124
    private static string GetName(NvPhysicalGpuHandle handle) {
moel@275
   125
      string gpuName;
moel@275
   126
      if (NVAPI.NvAPI_GPU_GetFullName(handle, out gpuName) == NvStatus.OK) {
moel@275
   127
        return "NVIDIA " + gpuName.Trim();
moel@275
   128
      } else {
moel@275
   129
        return "NVIDIA";
moel@166
   130
      }
moel@1
   131
    }
moel@1
   132
moel@165
   133
    public override HardwareType HardwareType {
moel@176
   134
      get { return HardwareType.GpuNvidia; }
moel@1
   135
    }
moel@1
   136
moel@1
   137
    private NvGPUThermalSettings GetThermalSettings() {
moel@1
   138
      NvGPUThermalSettings settings = new NvGPUThermalSettings();
moel@1
   139
      settings.Version = NVAPI.GPU_THERMAL_SETTINGS_VER;
moel@1
   140
      settings.Count = NVAPI.MAX_THERMAL_SENSORS_PER_GPU;
moel@1
   141
      settings.Sensor = new NvSensor[NVAPI.MAX_THERMAL_SENSORS_PER_GPU];
moel@309
   142
      if (!(NVAPI.NvAPI_GPU_GetThermalSettings != null &&
moel@140
   143
        NVAPI.NvAPI_GPU_GetThermalSettings(handle, (int)NvThermalTarget.ALL,
moel@309
   144
          ref settings) == NvStatus.OK)) 
moel@309
   145
      {
moel@309
   146
        settings.Count = 0;
moel@309
   147
      }       
moel@309
   148
      return settings;    
moel@309
   149
    }
moel@309
   150
moel@309
   151
    private NvGPUCoolerSettings GetCoolerSettings() {
moel@309
   152
      NvGPUCoolerSettings settings = new NvGPUCoolerSettings();
moel@309
   153
      settings.Version = NVAPI.GPU_COOLER_SETTINGS_VER;
moel@309
   154
      settings.Cooler = new NvCooler[NVAPI.MAX_COOLER_PER_GPU];
moel@309
   155
      if (!(NVAPI.NvAPI_GPU_GetCoolerSettings != null &&
moel@309
   156
        NVAPI.NvAPI_GPU_GetCoolerSettings(handle, 0, 
moel@309
   157
          ref settings) == NvStatus.OK)) 
moel@309
   158
      {
moel@309
   159
        settings.Count = 0;
moel@38
   160
      }
moel@309
   161
      return settings;  
moel@1
   162
    }
moel@1
   163
moel@140
   164
    private uint[] GetClocks() {
moel@166
   165
      NvClocks allClocks = new NvClocks();
moel@166
   166
      allClocks.Version = NVAPI.GPU_CLOCKS_VER;
moel@166
   167
      allClocks.Clock = new uint[NVAPI.MAX_CLOCKS_PER_GPU];
moel@140
   168
      if (NVAPI.NvAPI_GPU_GetAllClocks != null &&
moel@166
   169
        NVAPI.NvAPI_GPU_GetAllClocks(handle, ref allClocks) == NvStatus.OK) {
moel@166
   170
        return allClocks.Clock;
moel@140
   171
      }
moel@140
   172
      return null;
moel@140
   173
    }
moel@140
   174
moel@110
   175
    public override void Update() {
moel@1
   176
      NvGPUThermalSettings settings = GetThermalSettings();
moel@309
   177
      foreach (Sensor sensor in temperatures)
moel@38
   178
        sensor.Value = settings.Sensor[sensor.Index].CurrentTemp;
moel@38
   179
moel@38
   180
      if (fan != null) {
moel@38
   181
        int value = 0;
moel@38
   182
        NVAPI.NvAPI_GPU_GetTachReading(handle, out value);
moel@38
   183
        fan.Value = value;
moel@38
   184
      }
moel@140
   185
moel@140
   186
      uint[] values = GetClocks();
moel@140
   187
      if (values != null) {
moel@140
   188
        clocks[0].Value = 0.001f * values[0];
moel@140
   189
        clocks[1].Value = 0.001f * values[8];
moel@140
   190
        clocks[2].Value = 0.001f * values[14];
moel@140
   191
        if (values[30] != 0) {
moel@140
   192
          clocks[0].Value = 0.0005f * values[30];
moel@140
   193
          clocks[2].Value = 0.001f * values[30];
moel@140
   194
        }
moel@140
   195
      }
moel@140
   196
moel@140
   197
      NvPStates states = new NvPStates();
moel@140
   198
      states.Version = NVAPI.GPU_PSTATES_VER;
moel@140
   199
      states.PStates = new NvPState[NVAPI.MAX_PSTATES_PER_GPU];
moel@309
   200
      if (NVAPI.NvAPI_GPU_GetPStates != null &&
moel@140
   201
        NVAPI.NvAPI_GPU_GetPStates(handle, ref states) == NvStatus.OK) {
moel@140
   202
        for (int i = 0; i < 3; i++)
moel@140
   203
          if (states.PStates[i].Present) {
moel@140
   204
            loads[i].Value = states.PStates[i].Percentage;
moel@140
   205
            ActivateSensor(loads[i]);
moel@140
   206
          }
moel@140
   207
      } else {
moel@140
   208
        NvUsages usages = new NvUsages();
moel@140
   209
        usages.Version = NVAPI.GPU_USAGES_VER;
moel@140
   210
        usages.Usage = new uint[NVAPI.MAX_USAGES_PER_GPU];
moel@140
   211
        if (NVAPI.NvAPI_GPU_GetUsages != null &&
moel@140
   212
          NVAPI.NvAPI_GPU_GetUsages(handle, ref usages) == NvStatus.OK) {
moel@140
   213
          loads[0].Value = usages.Usage[2];
moel@140
   214
          loads[1].Value = usages.Usage[6];
moel@140
   215
          loads[2].Value = usages.Usage[10];
moel@140
   216
          for (int i = 0; i < 3; i++)
moel@140
   217
            ActivateSensor(loads[i]);
moel@140
   218
        }
moel@140
   219
      }
moel@140
   220
moel@309
   221
moel@309
   222
      NvGPUCoolerSettings coolerSettings = GetCoolerSettings();
moel@309
   223
      if (coolerSettings.Count > 0) {
moel@140
   224
        control.Value = coolerSettings.Cooler[0].CurrentLevel;
moel@140
   225
        ActivateSensor(control);
moel@140
   226
      }
moel@140
   227
moel@140
   228
      NvMemoryInfo memoryInfo = new NvMemoryInfo();
moel@140
   229
      memoryInfo.Version = NVAPI.GPU_MEMORY_INFO_VER;
moel@140
   230
      memoryInfo.Values = new uint[NVAPI.MAX_MEMORY_VALUES_PER_GPU];
moel@140
   231
      if (NVAPI.NvAPI_GPU_GetMemoryInfo != null && displayHandle.HasValue &&
moel@309
   232
        NVAPI.NvAPI_GPU_GetMemoryInfo(displayHandle.Value, ref memoryInfo) ==
moel@309
   233
        NvStatus.OK) {
moel@140
   234
        uint totalMemory = memoryInfo.Values[0];
moel@140
   235
        uint freeMemory = memoryInfo.Values[4];
moel@140
   236
        float usedMemory = Math.Max(totalMemory - freeMemory, 0);
moel@140
   237
        memoryLoad.Value = 100f * usedMemory / totalMemory;
moel@140
   238
        ActivateSensor(memoryLoad);
moel@140
   239
      }
moel@140
   240
    }
moel@140
   241
moel@140
   242
    public override string GetReport() {
moel@140
   243
      StringBuilder r = new StringBuilder();
moel@140
   244
moel@140
   245
      r.AppendLine("Nvidia GPU");
moel@140
   246
      r.AppendLine();
moel@140
   247
moel@140
   248
      r.AppendFormat("Name: {0}{1}", name, Environment.NewLine);
moel@140
   249
      r.AppendFormat("Index: {0}{1}", adapterIndex, Environment.NewLine);
moel@309
   250
moel@309
   251
      if (displayHandle.HasValue && NVAPI.NvAPI_GetDisplayDriverVersion != null) {
moel@140
   252
        NvDisplayDriverVersion driverVersion = new NvDisplayDriverVersion();
moel@140
   253
        driverVersion.Version = NVAPI.DISPLAY_DRIVER_VERSION_VER;
moel@140
   254
        if (NVAPI.NvAPI_GetDisplayDriverVersion(displayHandle.Value,
moel@140
   255
          ref driverVersion) == NvStatus.OK) {
moel@140
   256
          r.Append("Driver Version: ");
moel@140
   257
          r.Append(driverVersion.DriverVersion / 100);
moel@140
   258
          r.Append(".");
moel@309
   259
          r.Append((driverVersion.DriverVersion % 100).ToString("00",
moel@167
   260
            CultureInfo.InvariantCulture));
moel@140
   261
          r.AppendLine();
moel@140
   262
          r.Append("Driver Branch: ");
moel@140
   263
          r.AppendLine(driverVersion.BuildBranch);
moel@140
   264
        }
moel@140
   265
      }
moel@140
   266
      r.AppendLine();
moel@140
   267
moel@140
   268
      if (NVAPI.NvAPI_GPU_GetThermalSettings != null) {
moel@140
   269
        NvGPUThermalSettings settings = new NvGPUThermalSettings();
moel@140
   270
        settings.Version = NVAPI.GPU_THERMAL_SETTINGS_VER;
moel@140
   271
        settings.Count = NVAPI.MAX_THERMAL_SENSORS_PER_GPU;
moel@140
   272
        settings.Sensor = new NvSensor[NVAPI.MAX_THERMAL_SENSORS_PER_GPU];
moel@140
   273
moel@140
   274
        NvStatus status = NVAPI.NvAPI_GPU_GetThermalSettings(handle,
moel@140
   275
          (int)NvThermalTarget.ALL, ref settings);
moel@140
   276
moel@140
   277
        r.AppendLine("Thermal Settings");
moel@140
   278
        r.AppendLine();
moel@140
   279
        if (status == NvStatus.OK) {
moel@140
   280
          for (int i = 0; i < settings.Count; i++) {
moel@140
   281
            r.AppendFormat(" Sensor[{0}].Controller: {1}{2}", i,
moel@140
   282
              settings.Sensor[i].Controller, Environment.NewLine);
moel@140
   283
            r.AppendFormat(" Sensor[{0}].DefaultMinTemp: {1}{2}", i,
moel@140
   284
              settings.Sensor[i].DefaultMinTemp, Environment.NewLine);
moel@140
   285
            r.AppendFormat(" Sensor[{0}].DefaultMaxTemp: {1}{2}", i,
moel@140
   286
              settings.Sensor[i].DefaultMaxTemp, Environment.NewLine);
moel@140
   287
            r.AppendFormat(" Sensor[{0}].CurrentTemp: {1}{2}", i,
moel@140
   288
              settings.Sensor[i].CurrentTemp, Environment.NewLine);
moel@140
   289
            r.AppendFormat(" Sensor[{0}].Target: {1}{2}", i,
moel@140
   290
              settings.Sensor[i].Target, Environment.NewLine);
moel@140
   291
          }
moel@140
   292
        } else {
moel@140
   293
          r.Append(" Status: ");
moel@140
   294
          r.AppendLine(status.ToString());
moel@140
   295
        }
moel@140
   296
        r.AppendLine();
moel@309
   297
      }
moel@140
   298
moel@140
   299
      if (NVAPI.NvAPI_GPU_GetAllClocks != null) {
moel@166
   300
        NvClocks allClocks = new NvClocks();
moel@166
   301
        allClocks.Version = NVAPI.GPU_CLOCKS_VER;
moel@166
   302
        allClocks.Clock = new uint[NVAPI.MAX_CLOCKS_PER_GPU];
moel@166
   303
        NvStatus status = NVAPI.NvAPI_GPU_GetAllClocks(handle, ref allClocks);
moel@140
   304
moel@140
   305
        r.AppendLine("Clocks");
moel@140
   306
        r.AppendLine();
moel@140
   307
        if (status == NvStatus.OK) {
moel@166
   308
          for (int i = 0; i < allClocks.Clock.Length; i++)
moel@166
   309
            if (allClocks.Clock[i] > 0) {
moel@166
   310
              r.AppendFormat(" Clock[{0}]: {1}{2}", i, allClocks.Clock[i],
moel@140
   311
                Environment.NewLine);
moel@140
   312
            }
moel@140
   313
        } else {
moel@140
   314
          r.Append(" Status: ");
moel@140
   315
          r.AppendLine(status.ToString());
moel@140
   316
        }
moel@140
   317
        r.AppendLine();
moel@309
   318
      }
moel@309
   319
moel@140
   320
      if (NVAPI.NvAPI_GPU_GetTachReading != null) {
moel@309
   321
        int tachValue;
moel@140
   322
        NvStatus status = NVAPI.NvAPI_GPU_GetTachReading(handle, out tachValue);
moel@140
   323
moel@140
   324
        r.AppendLine("Tachometer");
moel@140
   325
        r.AppendLine();
moel@140
   326
        if (status == NvStatus.OK) {
moel@140
   327
          r.AppendFormat(" Value: {0}{1}", tachValue, Environment.NewLine);
moel@140
   328
        } else {
moel@140
   329
          r.Append(" Status: ");
moel@140
   330
          r.AppendLine(status.ToString());
moel@140
   331
        }
moel@140
   332
        r.AppendLine();
moel@140
   333
      }
moel@140
   334
moel@140
   335
      if (NVAPI.NvAPI_GPU_GetPStates != null) {
moel@140
   336
        NvPStates states = new NvPStates();
moel@140
   337
        states.Version = NVAPI.GPU_PSTATES_VER;
moel@140
   338
        states.PStates = new NvPState[NVAPI.MAX_PSTATES_PER_GPU];
moel@140
   339
        NvStatus status = NVAPI.NvAPI_GPU_GetPStates(handle, ref states);
moel@140
   340
moel@140
   341
        r.AppendLine("P-States");
moel@140
   342
        r.AppendLine();
moel@140
   343
        if (status == NvStatus.OK) {
moel@140
   344
          for (int i = 0; i < states.PStates.Length; i++)
moel@140
   345
            if (states.PStates[i].Present)
moel@140
   346
              r.AppendFormat(" Percentage[{0}]: {1}{2}", i,
moel@140
   347
                states.PStates[i].Percentage, Environment.NewLine);
moel@140
   348
        } else {
moel@140
   349
          r.Append(" Status: ");
moel@140
   350
          r.AppendLine(status.ToString());
moel@140
   351
        }
moel@140
   352
        r.AppendLine();
moel@140
   353
      }
moel@140
   354
moel@140
   355
      if (NVAPI.NvAPI_GPU_GetUsages != null) {
moel@140
   356
        NvUsages usages = new NvUsages();
moel@140
   357
        usages.Version = NVAPI.GPU_USAGES_VER;
moel@140
   358
        usages.Usage = new uint[NVAPI.MAX_USAGES_PER_GPU];
moel@140
   359
        NvStatus status = NVAPI.NvAPI_GPU_GetUsages(handle, ref usages);
moel@309
   360
moel@140
   361
        r.AppendLine("Usages");
moel@140
   362
        r.AppendLine();
moel@140
   363
        if (status == NvStatus.OK) {
moel@140
   364
          for (int i = 0; i < usages.Usage.Length; i++)
moel@140
   365
            if (usages.Usage[i] > 0)
moel@140
   366
              r.AppendFormat(" Usage[{0}]: {1}{2}", i,
moel@140
   367
                usages.Usage[i], Environment.NewLine);
moel@140
   368
        } else {
moel@140
   369
          r.Append(" Status: ");
moel@140
   370
          r.AppendLine(status.ToString());
moel@140
   371
        }
moel@140
   372
        r.AppendLine();
moel@140
   373
      }
moel@140
   374
moel@140
   375
      if (NVAPI.NvAPI_GPU_GetCoolerSettings != null) {
moel@140
   376
        NvGPUCoolerSettings settings = new NvGPUCoolerSettings();
moel@140
   377
        settings.Version = NVAPI.GPU_COOLER_SETTINGS_VER;
moel@140
   378
        settings.Cooler = new NvCooler[NVAPI.MAX_COOLER_PER_GPU];
moel@140
   379
        NvStatus status =
moel@140
   380
          NVAPI.NvAPI_GPU_GetCoolerSettings(handle, 0, ref settings);
moel@140
   381
moel@140
   382
        r.AppendLine("Cooler Settings");
moel@140
   383
        r.AppendLine();
moel@140
   384
        if (status == NvStatus.OK) {
moel@140
   385
          for (int i = 0; i < settings.Count; i++) {
moel@140
   386
            r.AppendFormat(" Cooler[{0}].Type: {1}{2}", i,
moel@140
   387
              settings.Cooler[i].Type, Environment.NewLine);
moel@140
   388
            r.AppendFormat(" Cooler[{0}].Controller: {1}{2}", i,
moel@140
   389
              settings.Cooler[i].Controller, Environment.NewLine);
moel@140
   390
            r.AppendFormat(" Cooler[{0}].DefaultMin: {1}{2}", i,
moel@140
   391
              settings.Cooler[i].DefaultMin, Environment.NewLine);
moel@140
   392
            r.AppendFormat(" Cooler[{0}].DefaultMax: {1}{2}", i,
moel@140
   393
              settings.Cooler[i].DefaultMax, Environment.NewLine);
moel@140
   394
            r.AppendFormat(" Cooler[{0}].CurrentMin: {1}{2}", i,
moel@140
   395
              settings.Cooler[i].CurrentMin, Environment.NewLine);
moel@140
   396
            r.AppendFormat(" Cooler[{0}].CurrentMax: {1}{2}", i,
moel@140
   397
              settings.Cooler[i].CurrentMax, Environment.NewLine);
moel@140
   398
            r.AppendFormat(" Cooler[{0}].CurrentLevel: {1}{2}", i,
moel@140
   399
              settings.Cooler[i].CurrentLevel, Environment.NewLine);
moel@140
   400
            r.AppendFormat(" Cooler[{0}].DefaultPolicy: {1}{2}", i,
moel@140
   401
              settings.Cooler[i].DefaultPolicy, Environment.NewLine);
moel@140
   402
            r.AppendFormat(" Cooler[{0}].CurrentPolicy: {1}{2}", i,
moel@140
   403
              settings.Cooler[i].CurrentPolicy, Environment.NewLine);
moel@140
   404
            r.AppendFormat(" Cooler[{0}].Target: {1}{2}", i,
moel@140
   405
              settings.Cooler[i].Target, Environment.NewLine);
moel@140
   406
            r.AppendFormat(" Cooler[{0}].ControlType: {1}{2}", i,
moel@140
   407
              settings.Cooler[i].ControlType, Environment.NewLine);
moel@140
   408
            r.AppendFormat(" Cooler[{0}].Active: {1}{2}", i,
moel@140
   409
              settings.Cooler[i].Active, Environment.NewLine);
moel@140
   410
          }
moel@140
   411
        } else {
moel@140
   412
          r.Append(" Status: ");
moel@140
   413
          r.AppendLine(status.ToString());
moel@140
   414
        }
moel@140
   415
        r.AppendLine();
moel@140
   416
      }
moel@140
   417
moel@140
   418
      if (NVAPI.NvAPI_GPU_GetMemoryInfo != null && displayHandle.HasValue) {
moel@140
   419
        NvMemoryInfo memoryInfo = new NvMemoryInfo();
moel@140
   420
        memoryInfo.Version = NVAPI.GPU_MEMORY_INFO_VER;
moel@140
   421
        memoryInfo.Values = new uint[NVAPI.MAX_MEMORY_VALUES_PER_GPU];
moel@309
   422
        NvStatus status = NVAPI.NvAPI_GPU_GetMemoryInfo(displayHandle.Value,
moel@140
   423
          ref memoryInfo);
moel@140
   424
moel@140
   425
        r.AppendLine("Memory Info");
moel@140
   426
        r.AppendLine();
moel@140
   427
        if (status == NvStatus.OK) {
moel@140
   428
          for (int i = 0; i < memoryInfo.Values.Length; i++)
moel@140
   429
            r.AppendFormat(" Value[{0}]: {1}{2}", i,
moel@140
   430
                memoryInfo.Values[i], Environment.NewLine);
moel@140
   431
        } else {
moel@140
   432
          r.Append(" Status: ");
moel@140
   433
          r.AppendLine(status.ToString());
moel@140
   434
        }
moel@140
   435
        r.AppendLine();
moel@140
   436
      }
moel@140
   437
moel@140
   438
      return r.ToString();
moel@1
   439
    }
moel@309
   440
moel@309
   441
    private void SoftwareControlValueChanged(IControl control) {
moel@309
   442
      SaveDefaultFanSpeed();
moel@309
   443
      NvGPUCoolerLevels coolerLevels = new NvGPUCoolerLevels();
moel@309
   444
      coolerLevels.Version = NVAPI.GPU_COOLER_LEVELS_VER;
moel@309
   445
      coolerLevels.Levels = new NvLevel[NVAPI.MAX_COOLER_PER_GPU];
moel@309
   446
      coolerLevels.Levels[0].Level = (int)control.SoftwareValue;
moel@309
   447
      coolerLevels.Levels[0].Policy = 1;
moel@309
   448
      NVAPI.NvAPI_GPU_SetCoolerLevels(handle, 0, ref coolerLevels);
moel@309
   449
    }
moel@309
   450
moel@309
   451
    private void SaveDefaultFanSpeed() {
moel@309
   452
      if (!restoreDefaultFanSpeedRequired) {
moel@309
   453
        NvGPUCoolerSettings coolerSettings = GetCoolerSettings();
moel@309
   454
        if (coolerSettings.Count > 0) {
moel@309
   455
          restoreDefaultFanSpeedRequired = true;
moel@309
   456
          initialFanSpeedValue.Level = coolerSettings.Cooler[0].CurrentLevel;
moel@309
   457
          initialFanSpeedValue.Policy = coolerSettings.Cooler[0].CurrentPolicy;
moel@309
   458
        }
moel@309
   459
      }
moel@309
   460
    }
moel@309
   461
moel@309
   462
    private void ControlModeChanged(IControl control) {
moel@309
   463
      if (control.ControlMode == ControlMode.Default) {
moel@309
   464
        RestoreDefaultFanSpeed();
moel@309
   465
      } else {
moel@309
   466
        SoftwareControlValueChanged(control);
moel@309
   467
      }
moel@309
   468
    }
moel@309
   469
moel@309
   470
    private void RestoreDefaultFanSpeed() {
moel@309
   471
      if (restoreDefaultFanSpeedRequired) {
moel@309
   472
        NvGPUCoolerLevels coolerLevels = new NvGPUCoolerLevels();
moel@309
   473
        coolerLevels.Version = NVAPI.GPU_COOLER_LEVELS_VER;
moel@309
   474
        coolerLevels.Levels = new NvLevel[NVAPI.MAX_COOLER_PER_GPU];
moel@309
   475
        coolerLevels.Levels[0] = initialFanSpeedValue;
moel@309
   476
        NVAPI.NvAPI_GPU_SetCoolerLevels(handle, 0, ref coolerLevels);
moel@309
   477
        restoreDefaultFanSpeedRequired = false;
moel@309
   478
      }
moel@309
   479
    }
moel@1
   480
  }
moel@1
   481
}