Added support for new Samsung SSDs (like Samsung SSD 840 PRO).
3 This Source Code Form is subject to the terms of the Mozilla Public
4 License, v. 2.0. If a copy of the MPL was not distributed with this
5 file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 Copyright (C) 2009-2012 Michael Möller <mmoeller@openhardwaremonitor.org>
8 Copyright (C) 2011 Christian Vallières
13 using System.Globalization;
16 namespace OpenHardwareMonitor.Hardware.Nvidia {
17 internal class NvidiaGPU : Hardware {
19 private readonly int adapterIndex;
20 private readonly NvPhysicalGpuHandle handle;
21 private readonly NvDisplayHandle? displayHandle;
23 private readonly Sensor[] temperatures;
24 private readonly Sensor fan;
25 private readonly Sensor[] clocks;
26 private readonly Sensor[] loads;
27 private readonly Sensor control;
28 private readonly Sensor memoryLoad;
29 private readonly Control fanControl;
31 private bool restoreDefaultFanSpeedRequired;
32 private NvLevel initialFanSpeedValue;
34 public NvidiaGPU(int adapterIndex, NvPhysicalGpuHandle handle,
35 NvDisplayHandle? displayHandle, ISettings settings)
36 : base(GetName(handle), new Identifier("nvidiagpu",
37 adapterIndex.ToString(CultureInfo.InvariantCulture)), settings) {
38 this.adapterIndex = adapterIndex;
40 this.displayHandle = displayHandle;
42 NvGPUThermalSettings thermalSettings = GetThermalSettings();
43 temperatures = new Sensor[thermalSettings.Count];
44 for (int i = 0; i < temperatures.Length; i++) {
45 NvSensor sensor = thermalSettings.Sensor[i];
47 switch (sensor.Target) {
48 case NvThermalTarget.BOARD: name = "GPU Board"; break;
49 case NvThermalTarget.GPU: name = "GPU Core"; break;
50 case NvThermalTarget.MEMORY: name = "GPU Memory"; break;
51 case NvThermalTarget.POWER_SUPPLY: name = "GPU Power Supply"; break;
52 case NvThermalTarget.UNKNOWN: name = "GPU Unknown"; break;
53 default: name = "GPU"; break;
55 temperatures[i] = new Sensor(name, i, SensorType.Temperature, this,
56 new ParameterDescription[0], settings);
57 ActivateSensor(temperatures[i]);
61 if (NVAPI.NvAPI_GPU_GetTachReading != null &&
62 NVAPI.NvAPI_GPU_GetTachReading(handle, out value) == NvStatus.OK) {
64 fan = new Sensor("GPU", 0, SensorType.Fan, this, settings);
69 clocks = new Sensor[3];
70 clocks[0] = new Sensor("GPU Core", 0, SensorType.Clock, this, settings);
71 clocks[1] = new Sensor("GPU Memory", 1, SensorType.Clock, this, settings);
72 clocks[2] = new Sensor("GPU Shader", 2, SensorType.Clock, this, settings);
73 for (int i = 0; i < clocks.Length; i++)
74 ActivateSensor(clocks[i]);
76 loads = new Sensor[3];
77 loads[0] = new Sensor("GPU Core", 0, SensorType.Load, this, settings);
78 loads[1] = new Sensor("GPU Memory Controller", 1, SensorType.Load, this, settings);
79 loads[2] = new Sensor("GPU Video Engine", 2, SensorType.Load, this, settings);
80 memoryLoad = new Sensor("GPU Memory", 3, SensorType.Load, this, settings);
82 control = new Sensor("GPU Fan", 0, SensorType.Control, this, settings);
84 NvGPUCoolerSettings coolerSettings = GetCoolerSettings();
85 if (coolerSettings.Count > 0) {
86 fanControl = new Control(control, settings,
87 coolerSettings.Cooler[0].DefaultMin,
88 coolerSettings.Cooler[0].DefaultMax);
89 fanControl.ControlModeChanged += ControlModeChanged;
90 fanControl.SoftwareControlValueChanged += SoftwareControlValueChanged;
91 ControlModeChanged(fanControl);
92 control.Control = fanControl;
97 private static string GetName(NvPhysicalGpuHandle handle) {
99 if (NVAPI.NvAPI_GPU_GetFullName(handle, out gpuName) == NvStatus.OK) {
100 return "NVIDIA " + gpuName.Trim();
106 public override HardwareType HardwareType {
107 get { return HardwareType.GpuNvidia; }
110 private NvGPUThermalSettings GetThermalSettings() {
111 NvGPUThermalSettings settings = new NvGPUThermalSettings();
112 settings.Version = NVAPI.GPU_THERMAL_SETTINGS_VER;
113 settings.Count = NVAPI.MAX_THERMAL_SENSORS_PER_GPU;
114 settings.Sensor = new NvSensor[NVAPI.MAX_THERMAL_SENSORS_PER_GPU];
115 if (!(NVAPI.NvAPI_GPU_GetThermalSettings != null &&
116 NVAPI.NvAPI_GPU_GetThermalSettings(handle, (int)NvThermalTarget.ALL,
117 ref settings) == NvStatus.OK))
124 private NvGPUCoolerSettings GetCoolerSettings() {
125 NvGPUCoolerSettings settings = new NvGPUCoolerSettings();
126 settings.Version = NVAPI.GPU_COOLER_SETTINGS_VER;
127 settings.Cooler = new NvCooler[NVAPI.MAX_COOLER_PER_GPU];
128 if (!(NVAPI.NvAPI_GPU_GetCoolerSettings != null &&
129 NVAPI.NvAPI_GPU_GetCoolerSettings(handle, 0,
130 ref settings) == NvStatus.OK))
137 private uint[] GetClocks() {
138 NvClocks allClocks = new NvClocks();
139 allClocks.Version = NVAPI.GPU_CLOCKS_VER;
140 allClocks.Clock = new uint[NVAPI.MAX_CLOCKS_PER_GPU];
141 if (NVAPI.NvAPI_GPU_GetAllClocks != null &&
142 NVAPI.NvAPI_GPU_GetAllClocks(handle, ref allClocks) == NvStatus.OK) {
143 return allClocks.Clock;
148 public override void Update() {
149 NvGPUThermalSettings settings = GetThermalSettings();
150 foreach (Sensor sensor in temperatures)
151 sensor.Value = settings.Sensor[sensor.Index].CurrentTemp;
155 NVAPI.NvAPI_GPU_GetTachReading(handle, out value);
159 uint[] values = GetClocks();
160 if (values != null) {
161 clocks[0].Value = 0.001f * values[0];
162 clocks[1].Value = 0.001f * values[8];
163 clocks[2].Value = 0.001f * values[14];
164 if (values[30] != 0) {
165 clocks[0].Value = 0.0005f * values[30];
166 clocks[2].Value = 0.001f * values[30];
170 NvPStates states = new NvPStates();
171 states.Version = NVAPI.GPU_PSTATES_VER;
172 states.PStates = new NvPState[NVAPI.MAX_PSTATES_PER_GPU];
173 if (NVAPI.NvAPI_GPU_GetPStates != null &&
174 NVAPI.NvAPI_GPU_GetPStates(handle, ref states) == NvStatus.OK) {
175 for (int i = 0; i < 3; i++)
176 if (states.PStates[i].Present) {
177 loads[i].Value = states.PStates[i].Percentage;
178 ActivateSensor(loads[i]);
181 NvUsages usages = new NvUsages();
182 usages.Version = NVAPI.GPU_USAGES_VER;
183 usages.Usage = new uint[NVAPI.MAX_USAGES_PER_GPU];
184 if (NVAPI.NvAPI_GPU_GetUsages != null &&
185 NVAPI.NvAPI_GPU_GetUsages(handle, ref usages) == NvStatus.OK) {
186 loads[0].Value = usages.Usage[2];
187 loads[1].Value = usages.Usage[6];
188 loads[2].Value = usages.Usage[10];
189 for (int i = 0; i < 3; i++)
190 ActivateSensor(loads[i]);
195 NvGPUCoolerSettings coolerSettings = GetCoolerSettings();
196 if (coolerSettings.Count > 0) {
197 control.Value = coolerSettings.Cooler[0].CurrentLevel;
198 ActivateSensor(control);
201 NvMemoryInfo memoryInfo = new NvMemoryInfo();
202 memoryInfo.Version = NVAPI.GPU_MEMORY_INFO_VER;
203 memoryInfo.Values = new uint[NVAPI.MAX_MEMORY_VALUES_PER_GPU];
204 if (NVAPI.NvAPI_GPU_GetMemoryInfo != null && displayHandle.HasValue &&
205 NVAPI.NvAPI_GPU_GetMemoryInfo(displayHandle.Value, ref memoryInfo) ==
207 uint totalMemory = memoryInfo.Values[0];
208 uint freeMemory = memoryInfo.Values[4];
209 float usedMemory = Math.Max(totalMemory - freeMemory, 0);
210 memoryLoad.Value = 100f * usedMemory / totalMemory;
211 ActivateSensor(memoryLoad);
215 public override string GetReport() {
216 StringBuilder r = new StringBuilder();
218 r.AppendLine("Nvidia GPU");
221 r.AppendFormat("Name: {0}{1}", name, Environment.NewLine);
222 r.AppendFormat("Index: {0}{1}", adapterIndex, Environment.NewLine);
224 if (displayHandle.HasValue && NVAPI.NvAPI_GetDisplayDriverVersion != null) {
225 NvDisplayDriverVersion driverVersion = new NvDisplayDriverVersion();
226 driverVersion.Version = NVAPI.DISPLAY_DRIVER_VERSION_VER;
227 if (NVAPI.NvAPI_GetDisplayDriverVersion(displayHandle.Value,
228 ref driverVersion) == NvStatus.OK) {
229 r.Append("Driver Version: ");
230 r.Append(driverVersion.DriverVersion / 100);
232 r.Append((driverVersion.DriverVersion % 100).ToString("00",
233 CultureInfo.InvariantCulture));
235 r.Append("Driver Branch: ");
236 r.AppendLine(driverVersion.BuildBranch);
241 if (NVAPI.NvAPI_GPU_GetPCIIdentifiers != null) {
242 uint deviceId, subSystemId, revisionId, extDeviceId;
244 NvStatus status = NVAPI.NvAPI_GPU_GetPCIIdentifiers(handle,
245 out deviceId, out subSystemId, out revisionId, out extDeviceId);
247 if (status == NvStatus.OK) {
248 r.Append("DeviceID: 0x");
249 r.AppendLine(deviceId.ToString("X", CultureInfo.InvariantCulture));
250 r.Append("SubSystemID: 0x");
251 r.AppendLine(subSystemId.ToString("X", CultureInfo.InvariantCulture));
252 r.Append("RevisionID: 0x");
253 r.AppendLine(revisionId.ToString("X", CultureInfo.InvariantCulture));
254 r.Append("ExtDeviceID: 0x");
255 r.AppendLine(extDeviceId.ToString("X", CultureInfo.InvariantCulture));
260 if (NVAPI.NvAPI_GPU_GetThermalSettings != null) {
261 NvGPUThermalSettings settings = new NvGPUThermalSettings();
262 settings.Version = NVAPI.GPU_THERMAL_SETTINGS_VER;
263 settings.Count = NVAPI.MAX_THERMAL_SENSORS_PER_GPU;
264 settings.Sensor = new NvSensor[NVAPI.MAX_THERMAL_SENSORS_PER_GPU];
266 NvStatus status = NVAPI.NvAPI_GPU_GetThermalSettings(handle,
267 (int)NvThermalTarget.ALL, ref settings);
269 r.AppendLine("Thermal Settings");
271 if (status == NvStatus.OK) {
272 for (int i = 0; i < settings.Count; i++) {
273 r.AppendFormat(" Sensor[{0}].Controller: {1}{2}", i,
274 settings.Sensor[i].Controller, Environment.NewLine);
275 r.AppendFormat(" Sensor[{0}].DefaultMinTemp: {1}{2}", i,
276 settings.Sensor[i].DefaultMinTemp, Environment.NewLine);
277 r.AppendFormat(" Sensor[{0}].DefaultMaxTemp: {1}{2}", i,
278 settings.Sensor[i].DefaultMaxTemp, Environment.NewLine);
279 r.AppendFormat(" Sensor[{0}].CurrentTemp: {1}{2}", i,
280 settings.Sensor[i].CurrentTemp, Environment.NewLine);
281 r.AppendFormat(" Sensor[{0}].Target: {1}{2}", i,
282 settings.Sensor[i].Target, Environment.NewLine);
285 r.Append(" Status: ");
286 r.AppendLine(status.ToString());
291 if (NVAPI.NvAPI_GPU_GetAllClocks != null) {
292 NvClocks allClocks = new NvClocks();
293 allClocks.Version = NVAPI.GPU_CLOCKS_VER;
294 allClocks.Clock = new uint[NVAPI.MAX_CLOCKS_PER_GPU];
295 NvStatus status = NVAPI.NvAPI_GPU_GetAllClocks(handle, ref allClocks);
297 r.AppendLine("Clocks");
299 if (status == NvStatus.OK) {
300 for (int i = 0; i < allClocks.Clock.Length; i++)
301 if (allClocks.Clock[i] > 0) {
302 r.AppendFormat(" Clock[{0}]: {1}{2}", i, allClocks.Clock[i],
303 Environment.NewLine);
306 r.Append(" Status: ");
307 r.AppendLine(status.ToString());
312 if (NVAPI.NvAPI_GPU_GetTachReading != null) {
314 NvStatus status = NVAPI.NvAPI_GPU_GetTachReading(handle, out tachValue);
316 r.AppendLine("Tachometer");
318 if (status == NvStatus.OK) {
319 r.AppendFormat(" Value: {0}{1}", tachValue, Environment.NewLine);
321 r.Append(" Status: ");
322 r.AppendLine(status.ToString());
327 if (NVAPI.NvAPI_GPU_GetPStates != null) {
328 NvPStates states = new NvPStates();
329 states.Version = NVAPI.GPU_PSTATES_VER;
330 states.PStates = new NvPState[NVAPI.MAX_PSTATES_PER_GPU];
331 NvStatus status = NVAPI.NvAPI_GPU_GetPStates(handle, ref states);
333 r.AppendLine("P-States");
335 if (status == NvStatus.OK) {
336 for (int i = 0; i < states.PStates.Length; i++)
337 if (states.PStates[i].Present)
338 r.AppendFormat(" Percentage[{0}]: {1}{2}", i,
339 states.PStates[i].Percentage, Environment.NewLine);
341 r.Append(" Status: ");
342 r.AppendLine(status.ToString());
347 if (NVAPI.NvAPI_GPU_GetUsages != null) {
348 NvUsages usages = new NvUsages();
349 usages.Version = NVAPI.GPU_USAGES_VER;
350 usages.Usage = new uint[NVAPI.MAX_USAGES_PER_GPU];
351 NvStatus status = NVAPI.NvAPI_GPU_GetUsages(handle, ref usages);
353 r.AppendLine("Usages");
355 if (status == NvStatus.OK) {
356 for (int i = 0; i < usages.Usage.Length; i++)
357 if (usages.Usage[i] > 0)
358 r.AppendFormat(" Usage[{0}]: {1}{2}", i,
359 usages.Usage[i], Environment.NewLine);
361 r.Append(" Status: ");
362 r.AppendLine(status.ToString());
367 if (NVAPI.NvAPI_GPU_GetCoolerSettings != null) {
368 NvGPUCoolerSettings settings = new NvGPUCoolerSettings();
369 settings.Version = NVAPI.GPU_COOLER_SETTINGS_VER;
370 settings.Cooler = new NvCooler[NVAPI.MAX_COOLER_PER_GPU];
372 NVAPI.NvAPI_GPU_GetCoolerSettings(handle, 0, ref settings);
374 r.AppendLine("Cooler Settings");
376 if (status == NvStatus.OK) {
377 for (int i = 0; i < settings.Count; i++) {
378 r.AppendFormat(" Cooler[{0}].Type: {1}{2}", i,
379 settings.Cooler[i].Type, Environment.NewLine);
380 r.AppendFormat(" Cooler[{0}].Controller: {1}{2}", i,
381 settings.Cooler[i].Controller, Environment.NewLine);
382 r.AppendFormat(" Cooler[{0}].DefaultMin: {1}{2}", i,
383 settings.Cooler[i].DefaultMin, Environment.NewLine);
384 r.AppendFormat(" Cooler[{0}].DefaultMax: {1}{2}", i,
385 settings.Cooler[i].DefaultMax, Environment.NewLine);
386 r.AppendFormat(" Cooler[{0}].CurrentMin: {1}{2}", i,
387 settings.Cooler[i].CurrentMin, Environment.NewLine);
388 r.AppendFormat(" Cooler[{0}].CurrentMax: {1}{2}", i,
389 settings.Cooler[i].CurrentMax, Environment.NewLine);
390 r.AppendFormat(" Cooler[{0}].CurrentLevel: {1}{2}", i,
391 settings.Cooler[i].CurrentLevel, Environment.NewLine);
392 r.AppendFormat(" Cooler[{0}].DefaultPolicy: {1}{2}", i,
393 settings.Cooler[i].DefaultPolicy, Environment.NewLine);
394 r.AppendFormat(" Cooler[{0}].CurrentPolicy: {1}{2}", i,
395 settings.Cooler[i].CurrentPolicy, Environment.NewLine);
396 r.AppendFormat(" Cooler[{0}].Target: {1}{2}", i,
397 settings.Cooler[i].Target, Environment.NewLine);
398 r.AppendFormat(" Cooler[{0}].ControlType: {1}{2}", i,
399 settings.Cooler[i].ControlType, Environment.NewLine);
400 r.AppendFormat(" Cooler[{0}].Active: {1}{2}", i,
401 settings.Cooler[i].Active, Environment.NewLine);
404 r.Append(" Status: ");
405 r.AppendLine(status.ToString());
410 if (NVAPI.NvAPI_GPU_GetMemoryInfo != null && displayHandle.HasValue) {
411 NvMemoryInfo memoryInfo = new NvMemoryInfo();
412 memoryInfo.Version = NVAPI.GPU_MEMORY_INFO_VER;
413 memoryInfo.Values = new uint[NVAPI.MAX_MEMORY_VALUES_PER_GPU];
414 NvStatus status = NVAPI.NvAPI_GPU_GetMemoryInfo(displayHandle.Value,
417 r.AppendLine("Memory Info");
419 if (status == NvStatus.OK) {
420 for (int i = 0; i < memoryInfo.Values.Length; i++)
421 r.AppendFormat(" Value[{0}]: {1}{2}", i,
422 memoryInfo.Values[i], Environment.NewLine);
424 r.Append(" Status: ");
425 r.AppendLine(status.ToString());
433 private void SoftwareControlValueChanged(IControl control) {
434 SaveDefaultFanSpeed();
435 NvGPUCoolerLevels coolerLevels = new NvGPUCoolerLevels();
436 coolerLevels.Version = NVAPI.GPU_COOLER_LEVELS_VER;
437 coolerLevels.Levels = new NvLevel[NVAPI.MAX_COOLER_PER_GPU];
438 coolerLevels.Levels[0].Level = (int)control.SoftwareValue;
439 coolerLevels.Levels[0].Policy = 1;
440 NVAPI.NvAPI_GPU_SetCoolerLevels(handle, 0, ref coolerLevels);
443 private void SaveDefaultFanSpeed() {
444 if (!restoreDefaultFanSpeedRequired) {
445 NvGPUCoolerSettings coolerSettings = GetCoolerSettings();
446 if (coolerSettings.Count > 0) {
447 restoreDefaultFanSpeedRequired = true;
448 initialFanSpeedValue.Level = coolerSettings.Cooler[0].CurrentLevel;
449 initialFanSpeedValue.Policy = coolerSettings.Cooler[0].CurrentPolicy;
454 private void ControlModeChanged(IControl control) {
455 if (control.ControlMode == ControlMode.Default) {
456 RestoreDefaultFanSpeed();
458 SoftwareControlValueChanged(control);
462 private void RestoreDefaultFanSpeed() {
463 if (restoreDefaultFanSpeedRequired) {
464 NvGPUCoolerLevels coolerLevels = new NvGPUCoolerLevels();
465 coolerLevels.Version = NVAPI.GPU_COOLER_LEVELS_VER;
466 coolerLevels.Levels = new NvLevel[NVAPI.MAX_COOLER_PER_GPU];
467 coolerLevels.Levels[0] = initialFanSpeedValue;
468 NVAPI.NvAPI_GPU_SetCoolerLevels(handle, 0, ref coolerLevels);
469 restoreDefaultFanSpeedRequired = false;