Fixed Issue 387. The new implementation does not try to start a ring 0 driver that already exists, but could not be opened. It tries to delete the driver and install it new. The driver is now stored temporarily in the application folder. The driver is not correctly removed on system shutdown.
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;