Hardware/Nvidia/NvidiaGPU.cs
author StephaneLenclud
Thu, 18 Apr 2013 23:25:10 +0200
branchMiniDisplay
changeset 444 9b09e2ee0968
parent 428 3c1cdc197b24
permissions -rw-r--r--
Front View plug-in does not init if no sensor added.
Fixing some format to make strings shorter.
Now trying to start SoundGraphAccess.exe process from same directory.
Packed mode now can display three sensors along with the current time.
moel@1
     1
/*
moel@1
     2
 
moel@344
     3
  This Source Code Form is subject to the terms of the Mozilla Public
moel@344
     4
  License, v. 2.0. If a copy of the MPL was not distributed with this
moel@344
     5
  file, You can obtain one at http://mozilla.org/MPL/2.0/.
moel@344
     6
 
moel@428
     7
  Copyright (C) 2009-2014 Michael Möller <mmoeller@openhardwaremonitor.org>
moel@344
     8
	Copyright (C) 2011 Christian Vallières
moel@1
     9
 
moel@1
    10
*/
moel@1
    11
moel@1
    12
using System;
moel@166
    13
using System.Globalization;
moel@140
    14
using System.Text;
moel@1
    15
moel@1
    16
namespace OpenHardwareMonitor.Hardware.Nvidia {
moel@195
    17
  internal class NvidiaGPU : Hardware {
moel@1
    18
moel@195
    19
    private readonly int adapterIndex;
moel@195
    20
    private readonly NvPhysicalGpuHandle handle;
moel@195
    21
    private readonly NvDisplayHandle? displayHandle;
moel@1
    22
moel@195
    23
    private readonly Sensor[] temperatures;
moel@195
    24
    private readonly Sensor fan;
moel@195
    25
    private readonly Sensor[] clocks;
moel@195
    26
    private readonly Sensor[] loads;
moel@195
    27
    private readonly Sensor control;
moel@195
    28
    private readonly Sensor memoryLoad;
moel@309
    29
    private readonly Control fanControl;
moel@38
    30
moel@309
    31
    public NvidiaGPU(int adapterIndex, NvPhysicalGpuHandle handle,
moel@309
    32
      NvDisplayHandle? displayHandle, ISettings settings)
moel@309
    33
      : base(GetName(handle), new Identifier("nvidiagpu",
moel@309
    34
          adapterIndex.ToString(CultureInfo.InvariantCulture)), settings) {
moel@56
    35
      this.adapterIndex = adapterIndex;
moel@56
    36
      this.handle = handle;
moel@140
    37
      this.displayHandle = displayHandle;
moel@1
    38
moel@165
    39
      NvGPUThermalSettings thermalSettings = GetThermalSettings();
moel@165
    40
      temperatures = new Sensor[thermalSettings.Count];
moel@56
    41
      for (int i = 0; i < temperatures.Length; i++) {
moel@165
    42
        NvSensor sensor = thermalSettings.Sensor[i];
moel@56
    43
        string name;
moel@56
    44
        switch (sensor.Target) {
moel@56
    45
          case NvThermalTarget.BOARD: name = "GPU Board"; break;
moel@56
    46
          case NvThermalTarget.GPU: name = "GPU Core"; break;
moel@56
    47
          case NvThermalTarget.MEMORY: name = "GPU Memory"; break;
moel@56
    48
          case NvThermalTarget.POWER_SUPPLY: name = "GPU Power Supply"; break;
moel@56
    49
          case NvThermalTarget.UNKNOWN: name = "GPU Unknown"; break;
moel@56
    50
          default: name = "GPU"; break;
moel@38
    51
        }
moel@165
    52
        temperatures[i] = new Sensor(name, i, SensorType.Temperature, this,
moel@165
    53
          new ParameterDescription[0], settings);
moel@56
    54
        ActivateSensor(temperatures[i]);
moel@56
    55
      }
moel@1
    56
moel@56
    57
      int value;
moel@56
    58
      if (NVAPI.NvAPI_GPU_GetTachReading != null &&
moel@56
    59
        NVAPI.NvAPI_GPU_GetTachReading(handle, out value) == NvStatus.OK) {
moel@430
    60
        if (value >= 0) {
moel@165
    61
          fan = new Sensor("GPU", 0, SensorType.Fan, this, settings);
moel@56
    62
          ActivateSensor(fan);
moel@1
    63
        }
moel@1
    64
      }
moel@140
    65
moel@140
    66
      clocks = new Sensor[3];
moel@165
    67
      clocks[0] = new Sensor("GPU Core", 0, SensorType.Clock, this, settings);
moel@165
    68
      clocks[1] = new Sensor("GPU Memory", 1, SensorType.Clock, this, settings);
moel@165
    69
      clocks[2] = new Sensor("GPU Shader", 2, SensorType.Clock, this, settings);
moel@140
    70
      for (int i = 0; i < clocks.Length; i++)
moel@140
    71
        ActivateSensor(clocks[i]);
moel@140
    72
moel@140
    73
      loads = new Sensor[3];
moel@165
    74
      loads[0] = new Sensor("GPU Core", 0, SensorType.Load, this, settings);
moel@165
    75
      loads[1] = new Sensor("GPU Memory Controller", 1, SensorType.Load, this, settings);
moel@165
    76
      loads[2] = new Sensor("GPU Video Engine", 2, SensorType.Load, this, settings);
moel@165
    77
      memoryLoad = new Sensor("GPU Memory", 3, SensorType.Load, this, settings);
moel@140
    78
moel@165
    79
      control = new Sensor("GPU Fan", 0, SensorType.Control, this, settings);
moel@309
    80
moel@309
    81
      NvGPUCoolerSettings coolerSettings = GetCoolerSettings();
moel@309
    82
      if (coolerSettings.Count > 0) {
moel@309
    83
        fanControl = new Control(control, settings,
moel@309
    84
          coolerSettings.Cooler[0].DefaultMin, 
moel@309
    85
          coolerSettings.Cooler[0].DefaultMax);
moel@309
    86
        fanControl.ControlModeChanged += ControlModeChanged;
moel@309
    87
        fanControl.SoftwareControlValueChanged += SoftwareControlValueChanged;
moel@309
    88
        ControlModeChanged(fanControl);
moel@309
    89
        control.Control = fanControl;
moel@309
    90
      }
moel@309
    91
      Update();
moel@1
    92
    }
moel@1
    93
moel@275
    94
    private static string GetName(NvPhysicalGpuHandle handle) {
moel@275
    95
      string gpuName;
moel@275
    96
      if (NVAPI.NvAPI_GPU_GetFullName(handle, out gpuName) == NvStatus.OK) {
moel@275
    97
        return "NVIDIA " + gpuName.Trim();
moel@275
    98
      } else {
moel@275
    99
        return "NVIDIA";
moel@166
   100
      }
moel@1
   101
    }
moel@1
   102
moel@165
   103
    public override HardwareType HardwareType {
moel@176
   104
      get { return HardwareType.GpuNvidia; }
moel@1
   105
    }
moel@1
   106
moel@1
   107
    private NvGPUThermalSettings GetThermalSettings() {
moel@1
   108
      NvGPUThermalSettings settings = new NvGPUThermalSettings();
moel@1
   109
      settings.Version = NVAPI.GPU_THERMAL_SETTINGS_VER;
moel@1
   110
      settings.Count = NVAPI.MAX_THERMAL_SENSORS_PER_GPU;
moel@1
   111
      settings.Sensor = new NvSensor[NVAPI.MAX_THERMAL_SENSORS_PER_GPU];
moel@309
   112
      if (!(NVAPI.NvAPI_GPU_GetThermalSettings != null &&
moel@140
   113
        NVAPI.NvAPI_GPU_GetThermalSettings(handle, (int)NvThermalTarget.ALL,
moel@309
   114
          ref settings) == NvStatus.OK)) 
moel@309
   115
      {
moel@309
   116
        settings.Count = 0;
moel@309
   117
      }       
moel@309
   118
      return settings;    
moel@309
   119
    }
moel@309
   120
moel@309
   121
    private NvGPUCoolerSettings GetCoolerSettings() {
moel@309
   122
      NvGPUCoolerSettings settings = new NvGPUCoolerSettings();
moel@309
   123
      settings.Version = NVAPI.GPU_COOLER_SETTINGS_VER;
moel@309
   124
      settings.Cooler = new NvCooler[NVAPI.MAX_COOLER_PER_GPU];
moel@309
   125
      if (!(NVAPI.NvAPI_GPU_GetCoolerSettings != null &&
moel@309
   126
        NVAPI.NvAPI_GPU_GetCoolerSettings(handle, 0, 
moel@309
   127
          ref settings) == NvStatus.OK)) 
moel@309
   128
      {
moel@309
   129
        settings.Count = 0;
moel@38
   130
      }
moel@309
   131
      return settings;  
moel@1
   132
    }
moel@1
   133
moel@140
   134
    private uint[] GetClocks() {
moel@166
   135
      NvClocks allClocks = new NvClocks();
moel@166
   136
      allClocks.Version = NVAPI.GPU_CLOCKS_VER;
moel@166
   137
      allClocks.Clock = new uint[NVAPI.MAX_CLOCKS_PER_GPU];
moel@140
   138
      if (NVAPI.NvAPI_GPU_GetAllClocks != null &&
moel@166
   139
        NVAPI.NvAPI_GPU_GetAllClocks(handle, ref allClocks) == NvStatus.OK) {
moel@166
   140
        return allClocks.Clock;
moel@140
   141
      }
moel@140
   142
      return null;
moel@140
   143
    }
moel@140
   144
moel@110
   145
    public override void Update() {
moel@1
   146
      NvGPUThermalSettings settings = GetThermalSettings();
moel@309
   147
      foreach (Sensor sensor in temperatures)
moel@38
   148
        sensor.Value = settings.Sensor[sensor.Index].CurrentTemp;
moel@38
   149
moel@38
   150
      if (fan != null) {
moel@38
   151
        int value = 0;
moel@38
   152
        NVAPI.NvAPI_GPU_GetTachReading(handle, out value);
moel@38
   153
        fan.Value = value;
moel@38
   154
      }
moel@140
   155
moel@140
   156
      uint[] values = GetClocks();
moel@140
   157
      if (values != null) {
moel@140
   158
        clocks[0].Value = 0.001f * values[0];
moel@140
   159
        clocks[1].Value = 0.001f * values[8];
moel@140
   160
        clocks[2].Value = 0.001f * values[14];
moel@140
   161
        if (values[30] != 0) {
moel@140
   162
          clocks[0].Value = 0.0005f * values[30];
moel@140
   163
          clocks[2].Value = 0.001f * values[30];
moel@140
   164
        }
moel@140
   165
      }
moel@140
   166
moel@140
   167
      NvPStates states = new NvPStates();
moel@140
   168
      states.Version = NVAPI.GPU_PSTATES_VER;
moel@140
   169
      states.PStates = new NvPState[NVAPI.MAX_PSTATES_PER_GPU];
moel@309
   170
      if (NVAPI.NvAPI_GPU_GetPStates != null &&
moel@140
   171
        NVAPI.NvAPI_GPU_GetPStates(handle, ref states) == NvStatus.OK) {
moel@140
   172
        for (int i = 0; i < 3; i++)
moel@140
   173
          if (states.PStates[i].Present) {
moel@140
   174
            loads[i].Value = states.PStates[i].Percentage;
moel@140
   175
            ActivateSensor(loads[i]);
moel@140
   176
          }
moel@140
   177
      } else {
moel@140
   178
        NvUsages usages = new NvUsages();
moel@140
   179
        usages.Version = NVAPI.GPU_USAGES_VER;
moel@140
   180
        usages.Usage = new uint[NVAPI.MAX_USAGES_PER_GPU];
moel@140
   181
        if (NVAPI.NvAPI_GPU_GetUsages != null &&
moel@140
   182
          NVAPI.NvAPI_GPU_GetUsages(handle, ref usages) == NvStatus.OK) {
moel@140
   183
          loads[0].Value = usages.Usage[2];
moel@140
   184
          loads[1].Value = usages.Usage[6];
moel@140
   185
          loads[2].Value = usages.Usage[10];
moel@140
   186
          for (int i = 0; i < 3; i++)
moel@140
   187
            ActivateSensor(loads[i]);
moel@140
   188
        }
moel@140
   189
      }
moel@140
   190
moel@309
   191
moel@309
   192
      NvGPUCoolerSettings coolerSettings = GetCoolerSettings();
moel@309
   193
      if (coolerSettings.Count > 0) {
moel@140
   194
        control.Value = coolerSettings.Cooler[0].CurrentLevel;
moel@140
   195
        ActivateSensor(control);
moel@140
   196
      }
moel@140
   197
moel@140
   198
      NvMemoryInfo memoryInfo = new NvMemoryInfo();
moel@140
   199
      memoryInfo.Version = NVAPI.GPU_MEMORY_INFO_VER;
moel@140
   200
      memoryInfo.Values = new uint[NVAPI.MAX_MEMORY_VALUES_PER_GPU];
moel@140
   201
      if (NVAPI.NvAPI_GPU_GetMemoryInfo != null && displayHandle.HasValue &&
moel@309
   202
        NVAPI.NvAPI_GPU_GetMemoryInfo(displayHandle.Value, ref memoryInfo) ==
moel@309
   203
        NvStatus.OK) {
moel@140
   204
        uint totalMemory = memoryInfo.Values[0];
moel@140
   205
        uint freeMemory = memoryInfo.Values[4];
moel@140
   206
        float usedMemory = Math.Max(totalMemory - freeMemory, 0);
moel@140
   207
        memoryLoad.Value = 100f * usedMemory / totalMemory;
moel@140
   208
        ActivateSensor(memoryLoad);
moel@140
   209
      }
moel@140
   210
    }
moel@140
   211
moel@140
   212
    public override string GetReport() {
moel@140
   213
      StringBuilder r = new StringBuilder();
moel@140
   214
moel@140
   215
      r.AppendLine("Nvidia GPU");
moel@140
   216
      r.AppendLine();
moel@140
   217
moel@140
   218
      r.AppendFormat("Name: {0}{1}", name, Environment.NewLine);
moel@140
   219
      r.AppendFormat("Index: {0}{1}", adapterIndex, Environment.NewLine);
moel@309
   220
moel@309
   221
      if (displayHandle.HasValue && NVAPI.NvAPI_GetDisplayDriverVersion != null) {
moel@140
   222
        NvDisplayDriverVersion driverVersion = new NvDisplayDriverVersion();
moel@140
   223
        driverVersion.Version = NVAPI.DISPLAY_DRIVER_VERSION_VER;
moel@140
   224
        if (NVAPI.NvAPI_GetDisplayDriverVersion(displayHandle.Value,
moel@140
   225
          ref driverVersion) == NvStatus.OK) {
moel@140
   226
          r.Append("Driver Version: ");
moel@140
   227
          r.Append(driverVersion.DriverVersion / 100);
moel@140
   228
          r.Append(".");
moel@309
   229
          r.Append((driverVersion.DriverVersion % 100).ToString("00",
moel@167
   230
            CultureInfo.InvariantCulture));
moel@140
   231
          r.AppendLine();
moel@140
   232
          r.Append("Driver Branch: ");
moel@140
   233
          r.AppendLine(driverVersion.BuildBranch);
moel@140
   234
        }
moel@140
   235
      }
moel@140
   236
      r.AppendLine();
moel@140
   237
moel@334
   238
      if (NVAPI.NvAPI_GPU_GetPCIIdentifiers != null) {
moel@334
   239
        uint deviceId, subSystemId, revisionId, extDeviceId;
moel@334
   240
moel@334
   241
        NvStatus status = NVAPI.NvAPI_GPU_GetPCIIdentifiers(handle, 
moel@334
   242
          out deviceId, out subSystemId, out revisionId, out extDeviceId);
moel@334
   243
moel@334
   244
        if (status == NvStatus.OK) {
moel@334
   245
          r.Append("DeviceID: 0x");
moel@334
   246
          r.AppendLine(deviceId.ToString("X", CultureInfo.InvariantCulture));
moel@334
   247
          r.Append("SubSystemID: 0x");
moel@334
   248
          r.AppendLine(subSystemId.ToString("X", CultureInfo.InvariantCulture));
moel@334
   249
          r.Append("RevisionID: 0x");
moel@334
   250
          r.AppendLine(revisionId.ToString("X", CultureInfo.InvariantCulture));
moel@334
   251
          r.Append("ExtDeviceID: 0x");
moel@334
   252
          r.AppendLine(extDeviceId.ToString("X", CultureInfo.InvariantCulture));
moel@334
   253
          r.AppendLine();
moel@334
   254
        }
moel@334
   255
      }
moel@334
   256
moel@140
   257
      if (NVAPI.NvAPI_GPU_GetThermalSettings != null) {
moel@140
   258
        NvGPUThermalSettings settings = new NvGPUThermalSettings();
moel@140
   259
        settings.Version = NVAPI.GPU_THERMAL_SETTINGS_VER;
moel@140
   260
        settings.Count = NVAPI.MAX_THERMAL_SENSORS_PER_GPU;
moel@140
   261
        settings.Sensor = new NvSensor[NVAPI.MAX_THERMAL_SENSORS_PER_GPU];
moel@140
   262
moel@140
   263
        NvStatus status = NVAPI.NvAPI_GPU_GetThermalSettings(handle,
moel@140
   264
          (int)NvThermalTarget.ALL, ref settings);
moel@140
   265
moel@140
   266
        r.AppendLine("Thermal Settings");
moel@140
   267
        r.AppendLine();
moel@140
   268
        if (status == NvStatus.OK) {
moel@140
   269
          for (int i = 0; i < settings.Count; i++) {
moel@140
   270
            r.AppendFormat(" Sensor[{0}].Controller: {1}{2}", i,
moel@140
   271
              settings.Sensor[i].Controller, Environment.NewLine);
moel@140
   272
            r.AppendFormat(" Sensor[{0}].DefaultMinTemp: {1}{2}", i,
moel@140
   273
              settings.Sensor[i].DefaultMinTemp, Environment.NewLine);
moel@140
   274
            r.AppendFormat(" Sensor[{0}].DefaultMaxTemp: {1}{2}", i,
moel@140
   275
              settings.Sensor[i].DefaultMaxTemp, Environment.NewLine);
moel@140
   276
            r.AppendFormat(" Sensor[{0}].CurrentTemp: {1}{2}", i,
moel@140
   277
              settings.Sensor[i].CurrentTemp, Environment.NewLine);
moel@140
   278
            r.AppendFormat(" Sensor[{0}].Target: {1}{2}", i,
moel@140
   279
              settings.Sensor[i].Target, Environment.NewLine);
moel@140
   280
          }
moel@140
   281
        } else {
moel@140
   282
          r.Append(" Status: ");
moel@140
   283
          r.AppendLine(status.ToString());
moel@140
   284
        }
moel@140
   285
        r.AppendLine();
moel@309
   286
      }
moel@140
   287
moel@140
   288
      if (NVAPI.NvAPI_GPU_GetAllClocks != null) {
moel@166
   289
        NvClocks allClocks = new NvClocks();
moel@166
   290
        allClocks.Version = NVAPI.GPU_CLOCKS_VER;
moel@166
   291
        allClocks.Clock = new uint[NVAPI.MAX_CLOCKS_PER_GPU];
moel@166
   292
        NvStatus status = NVAPI.NvAPI_GPU_GetAllClocks(handle, ref allClocks);
moel@140
   293
moel@140
   294
        r.AppendLine("Clocks");
moel@140
   295
        r.AppendLine();
moel@140
   296
        if (status == NvStatus.OK) {
moel@166
   297
          for (int i = 0; i < allClocks.Clock.Length; i++)
moel@166
   298
            if (allClocks.Clock[i] > 0) {
moel@166
   299
              r.AppendFormat(" Clock[{0}]: {1}{2}", i, allClocks.Clock[i],
moel@140
   300
                Environment.NewLine);
moel@140
   301
            }
moel@140
   302
        } else {
moel@140
   303
          r.Append(" Status: ");
moel@140
   304
          r.AppendLine(status.ToString());
moel@140
   305
        }
moel@140
   306
        r.AppendLine();
moel@309
   307
      }
moel@309
   308
moel@140
   309
      if (NVAPI.NvAPI_GPU_GetTachReading != null) {
moel@309
   310
        int tachValue;
moel@140
   311
        NvStatus status = NVAPI.NvAPI_GPU_GetTachReading(handle, out tachValue);
moel@140
   312
moel@140
   313
        r.AppendLine("Tachometer");
moel@140
   314
        r.AppendLine();
moel@140
   315
        if (status == NvStatus.OK) {
moel@140
   316
          r.AppendFormat(" Value: {0}{1}", tachValue, Environment.NewLine);
moel@140
   317
        } else {
moel@140
   318
          r.Append(" Status: ");
moel@140
   319
          r.AppendLine(status.ToString());
moel@140
   320
        }
moel@140
   321
        r.AppendLine();
moel@140
   322
      }
moel@140
   323
moel@140
   324
      if (NVAPI.NvAPI_GPU_GetPStates != null) {
moel@140
   325
        NvPStates states = new NvPStates();
moel@140
   326
        states.Version = NVAPI.GPU_PSTATES_VER;
moel@140
   327
        states.PStates = new NvPState[NVAPI.MAX_PSTATES_PER_GPU];
moel@140
   328
        NvStatus status = NVAPI.NvAPI_GPU_GetPStates(handle, ref states);
moel@140
   329
moel@140
   330
        r.AppendLine("P-States");
moel@140
   331
        r.AppendLine();
moel@140
   332
        if (status == NvStatus.OK) {
moel@140
   333
          for (int i = 0; i < states.PStates.Length; i++)
moel@140
   334
            if (states.PStates[i].Present)
moel@140
   335
              r.AppendFormat(" Percentage[{0}]: {1}{2}", i,
moel@140
   336
                states.PStates[i].Percentage, Environment.NewLine);
moel@140
   337
        } else {
moel@140
   338
          r.Append(" Status: ");
moel@140
   339
          r.AppendLine(status.ToString());
moel@140
   340
        }
moel@140
   341
        r.AppendLine();
moel@140
   342
      }
moel@140
   343
moel@140
   344
      if (NVAPI.NvAPI_GPU_GetUsages != null) {
moel@140
   345
        NvUsages usages = new NvUsages();
moel@140
   346
        usages.Version = NVAPI.GPU_USAGES_VER;
moel@140
   347
        usages.Usage = new uint[NVAPI.MAX_USAGES_PER_GPU];
moel@140
   348
        NvStatus status = NVAPI.NvAPI_GPU_GetUsages(handle, ref usages);
moel@309
   349
moel@140
   350
        r.AppendLine("Usages");
moel@140
   351
        r.AppendLine();
moel@140
   352
        if (status == NvStatus.OK) {
moel@140
   353
          for (int i = 0; i < usages.Usage.Length; i++)
moel@140
   354
            if (usages.Usage[i] > 0)
moel@140
   355
              r.AppendFormat(" Usage[{0}]: {1}{2}", i,
moel@140
   356
                usages.Usage[i], Environment.NewLine);
moel@140
   357
        } else {
moel@140
   358
          r.Append(" Status: ");
moel@140
   359
          r.AppendLine(status.ToString());
moel@140
   360
        }
moel@140
   361
        r.AppendLine();
moel@140
   362
      }
moel@140
   363
moel@140
   364
      if (NVAPI.NvAPI_GPU_GetCoolerSettings != null) {
moel@140
   365
        NvGPUCoolerSettings settings = new NvGPUCoolerSettings();
moel@140
   366
        settings.Version = NVAPI.GPU_COOLER_SETTINGS_VER;
moel@140
   367
        settings.Cooler = new NvCooler[NVAPI.MAX_COOLER_PER_GPU];
moel@140
   368
        NvStatus status =
moel@140
   369
          NVAPI.NvAPI_GPU_GetCoolerSettings(handle, 0, ref settings);
moel@140
   370
moel@140
   371
        r.AppendLine("Cooler Settings");
moel@140
   372
        r.AppendLine();
moel@140
   373
        if (status == NvStatus.OK) {
moel@140
   374
          for (int i = 0; i < settings.Count; i++) {
moel@140
   375
            r.AppendFormat(" Cooler[{0}].Type: {1}{2}", i,
moel@140
   376
              settings.Cooler[i].Type, Environment.NewLine);
moel@140
   377
            r.AppendFormat(" Cooler[{0}].Controller: {1}{2}", i,
moel@140
   378
              settings.Cooler[i].Controller, Environment.NewLine);
moel@140
   379
            r.AppendFormat(" Cooler[{0}].DefaultMin: {1}{2}", i,
moel@140
   380
              settings.Cooler[i].DefaultMin, Environment.NewLine);
moel@140
   381
            r.AppendFormat(" Cooler[{0}].DefaultMax: {1}{2}", i,
moel@140
   382
              settings.Cooler[i].DefaultMax, Environment.NewLine);
moel@140
   383
            r.AppendFormat(" Cooler[{0}].CurrentMin: {1}{2}", i,
moel@140
   384
              settings.Cooler[i].CurrentMin, Environment.NewLine);
moel@140
   385
            r.AppendFormat(" Cooler[{0}].CurrentMax: {1}{2}", i,
moel@140
   386
              settings.Cooler[i].CurrentMax, Environment.NewLine);
moel@140
   387
            r.AppendFormat(" Cooler[{0}].CurrentLevel: {1}{2}", i,
moel@140
   388
              settings.Cooler[i].CurrentLevel, Environment.NewLine);
moel@140
   389
            r.AppendFormat(" Cooler[{0}].DefaultPolicy: {1}{2}", i,
moel@140
   390
              settings.Cooler[i].DefaultPolicy, Environment.NewLine);
moel@140
   391
            r.AppendFormat(" Cooler[{0}].CurrentPolicy: {1}{2}", i,
moel@140
   392
              settings.Cooler[i].CurrentPolicy, Environment.NewLine);
moel@140
   393
            r.AppendFormat(" Cooler[{0}].Target: {1}{2}", i,
moel@140
   394
              settings.Cooler[i].Target, Environment.NewLine);
moel@140
   395
            r.AppendFormat(" Cooler[{0}].ControlType: {1}{2}", i,
moel@140
   396
              settings.Cooler[i].ControlType, Environment.NewLine);
moel@140
   397
            r.AppendFormat(" Cooler[{0}].Active: {1}{2}", i,
moel@140
   398
              settings.Cooler[i].Active, Environment.NewLine);
moel@140
   399
          }
moel@140
   400
        } else {
moel@140
   401
          r.Append(" Status: ");
moel@140
   402
          r.AppendLine(status.ToString());
moel@140
   403
        }
moel@140
   404
        r.AppendLine();
moel@140
   405
      }
moel@140
   406
moel@140
   407
      if (NVAPI.NvAPI_GPU_GetMemoryInfo != null && displayHandle.HasValue) {
moel@140
   408
        NvMemoryInfo memoryInfo = new NvMemoryInfo();
moel@140
   409
        memoryInfo.Version = NVAPI.GPU_MEMORY_INFO_VER;
moel@140
   410
        memoryInfo.Values = new uint[NVAPI.MAX_MEMORY_VALUES_PER_GPU];
moel@309
   411
        NvStatus status = NVAPI.NvAPI_GPU_GetMemoryInfo(displayHandle.Value,
moel@140
   412
          ref memoryInfo);
moel@140
   413
moel@140
   414
        r.AppendLine("Memory Info");
moel@140
   415
        r.AppendLine();
moel@140
   416
        if (status == NvStatus.OK) {
moel@140
   417
          for (int i = 0; i < memoryInfo.Values.Length; i++)
moel@140
   418
            r.AppendFormat(" Value[{0}]: {1}{2}", i,
moel@140
   419
                memoryInfo.Values[i], Environment.NewLine);
moel@140
   420
        } else {
moel@140
   421
          r.Append(" Status: ");
moel@140
   422
          r.AppendLine(status.ToString());
moel@140
   423
        }
moel@140
   424
        r.AppendLine();
moel@140
   425
      }
moel@140
   426
moel@140
   427
      return r.ToString();
moel@1
   428
    }
moel@309
   429
moel@309
   430
    private void SoftwareControlValueChanged(IControl control) {
moel@309
   431
      NvGPUCoolerLevels coolerLevels = new NvGPUCoolerLevels();
moel@309
   432
      coolerLevels.Version = NVAPI.GPU_COOLER_LEVELS_VER;
moel@309
   433
      coolerLevels.Levels = new NvLevel[NVAPI.MAX_COOLER_PER_GPU];
moel@309
   434
      coolerLevels.Levels[0].Level = (int)control.SoftwareValue;
moel@309
   435
      coolerLevels.Levels[0].Policy = 1;
moel@309
   436
      NVAPI.NvAPI_GPU_SetCoolerLevels(handle, 0, ref coolerLevels);
moel@309
   437
    }
moel@309
   438
moel@428
   439
    private void ControlModeChanged(IControl control) {
moel@428
   440
      switch (control.ControlMode) {
moel@428
   441
        case ControlMode.Undefined:
moel@428
   442
          return;
moel@428
   443
        case ControlMode.Default:
moel@428
   444
          SetDefaultFanSpeed();
moel@428
   445
          break;
moel@428
   446
        case ControlMode.Software:
moel@428
   447
          SoftwareControlValueChanged(control);
moel@428
   448
          break;
moel@428
   449
        default:
moel@428
   450
          return;
moel@309
   451
      }
moel@309
   452
    }
moel@309
   453
moel@428
   454
    private void SetDefaultFanSpeed() {
moel@428
   455
      NvGPUCoolerLevels coolerLevels = new NvGPUCoolerLevels();
moel@428
   456
      coolerLevels.Version = NVAPI.GPU_COOLER_LEVELS_VER;
moel@428
   457
      coolerLevels.Levels = new NvLevel[NVAPI.MAX_COOLER_PER_GPU];
moel@428
   458
      coolerLevels.Levels[0].Policy = 0x20;
moel@428
   459
      NVAPI.NvAPI_GPU_SetCoolerLevels(handle, 0, ref coolerLevels);
moel@309
   460
    }
moel@309
   461
moel@428
   462
    public override void Close() {
moel@428
   463
      if (this.fanControl != null) {
moel@428
   464
        this.fanControl.ControlModeChanged -= ControlModeChanged;
moel@428
   465
        this.fanControl.SoftwareControlValueChanged -=
moel@428
   466
          SoftwareControlValueChanged;
moel@428
   467
moel@428
   468
        if (this.fanControl.ControlMode != ControlMode.Undefined)
moel@428
   469
          SetDefaultFanSpeed();
moel@309
   470
      }
moel@428
   471
      base.Close();
moel@309
   472
    }
moel@1
   473
  }
moel@1
   474
}