Hardware/Nvidia/NvidiaGPU.cs
author moel.mich
Tue, 30 Dec 2014 16:02:52 +0000
changeset 428 3c1cdc197b24
parent 344 3145aadca3d2
child 430 6b24e39f1b84
permissions -rw-r--r--
Added a new "Undefined" control mode. Changed the GPU fan control to restore to default (auto) settings when the Open Hardware Monitor closes (unless the control remained in "Undefined" mode).
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@56
    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
}