Hardware/Nvidia/NVAPI.cs
author moel.mich
Tue, 09 Mar 2010 22:27:10 +0000
changeset 79 9cdbe1d8d12a
parent 60 0e62c377c08c
child 101 f8589379e32c
permissions -rw-r--r--
Changed the CPU clock calculation. If no invariant TSC is available, then the max CPU clock is estimated at startup under load, otherwise an average over one second is used.
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@1
    19
  Portions created by the Initial Developer are Copyright (C) 2009-2010
moel@1
    20
  the Initial Developer. All Rights Reserved.
moel@1
    21
moel@1
    22
  Contributor(s):
moel@1
    23
moel@1
    24
  Alternatively, the contents of this file may be used under the terms of
moel@1
    25
  either the GNU General Public License Version 2 or later (the "GPL"), or
moel@1
    26
  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
moel@1
    27
  in which case the provisions of the GPL or the LGPL are applicable instead
moel@1
    28
  of those above. If you wish to allow use of your version of this file only
moel@1
    29
  under the terms of either the GPL or the LGPL, and not to allow others to
moel@1
    30
  use your version of this file under the terms of the MPL, indicate your
moel@1
    31
  decision by deleting the provisions above and replace them with the notice
moel@1
    32
  and other provisions required by the GPL or the LGPL. If you do not delete
moel@1
    33
  the provisions above, a recipient may use your version of this file under
moel@1
    34
  the terms of any one of the MPL, the GPL or the LGPL.
moel@1
    35
 
moel@1
    36
*/
moel@1
    37
moel@1
    38
using System;
moel@1
    39
using System.Collections.Generic;
moel@1
    40
using System.Runtime.InteropServices;
moel@1
    41
using System.Text;
moel@1
    42
moel@1
    43
namespace OpenHardwareMonitor.Hardware.Nvidia {
moel@1
    44
moel@1
    45
  public enum NvStatus {
moel@1
    46
    OK = 0,
moel@1
    47
    ERROR = -1,
moel@1
    48
    LIBRARY_NOT_FOUND = -2,
moel@1
    49
    NO_IMPLEMENTATION = -3,
moel@1
    50
    API_NOT_INTIALIZED = -4,
moel@1
    51
    INVALID_ARGUMENT = -5,
moel@1
    52
    NVIDIA_DEVICE_NOT_FOUND = -6,
moel@1
    53
    END_ENUMERATION = -7,
moel@1
    54
    INVALID_HANDLE = -8,
moel@1
    55
    INCOMPATIBLE_STRUCT_VERSION = -9,
moel@1
    56
    HANDLE_INVALIDATED = -10,
moel@1
    57
    OPENGL_CONTEXT_NOT_CURRENT = -11,
moel@1
    58
    NO_GL_EXPERT = -12,
moel@1
    59
    INSTRUMENTATION_DISABLED = -13,
moel@1
    60
    EXPECTED_LOGICAL_GPU_HANDLE = -100,
moel@1
    61
    EXPECTED_PHYSICAL_GPU_HANDLE = -101,
moel@1
    62
    EXPECTED_DISPLAY_HANDLE = -102,
moel@1
    63
    INVALID_COMBINATION = -103,
moel@1
    64
    NOT_SUPPORTED = -104,
moel@1
    65
    PORTID_NOT_FOUND = -105,
moel@1
    66
    EXPECTED_UNATTACHED_DISPLAY_HANDLE = -106,
moel@1
    67
    INVALID_PERF_LEVEL = -107,
moel@1
    68
    DEVICE_BUSY = -108,
moel@1
    69
    NV_PERSIST_FILE_NOT_FOUND = -109,
moel@1
    70
    PERSIST_DATA_NOT_FOUND = -110,
moel@1
    71
    EXPECTED_TV_DISPLAY = -111,
moel@1
    72
    EXPECTED_TV_DISPLAY_ON_DCONNECTOR = -112,
moel@1
    73
    NO_ACTIVE_SLI_TOPOLOGY = -113,
moel@1
    74
    SLI_RENDERING_MODE_NOTALLOWED = -114,
moel@1
    75
    EXPECTED_DIGITAL_FLAT_PANEL = -115,
moel@1
    76
    ARGUMENT_EXCEED_MAX_SIZE = -116,
moel@1
    77
    DEVICE_SWITCHING_NOT_ALLOWED = -117,
moel@1
    78
    TESTING_CLOCKS_NOT_SUPPORTED = -118,
moel@1
    79
    UNKNOWN_UNDERSCAN_CONFIG = -119,
moel@1
    80
    TIMEOUT_RECONFIGURING_GPU_TOPO = -120,
moel@1
    81
    DATA_NOT_FOUND = -121,
moel@1
    82
    EXPECTED_ANALOG_DISPLAY = -122,
moel@1
    83
    NO_VIDLINK = -123,
moel@1
    84
    REQUIRES_REBOOT = -124,
moel@1
    85
    INVALID_HYBRID_MODE = -125,
moel@1
    86
    MIXED_TARGET_TYPES = -126,
moel@1
    87
    SYSWOW64_NOT_SUPPORTED = -127,
moel@1
    88
    IMPLICIT_SET_GPU_TOPOLOGY_CHANGE_NOT_ALLOWED = -128,
moel@1
    89
    REQUEST_USER_TO_CLOSE_NON_MIGRATABLE_APPS = -129,
moel@1
    90
    OUT_OF_MEMORY = -130,
moel@1
    91
    WAS_STILL_DRAWING = -131,
moel@1
    92
    FILE_NOT_FOUND = -132,
moel@1
    93
    TOO_MANY_UNIQUE_STATE_OBJECTS = -133,
moel@1
    94
    INVALID_CALL = -134,
moel@1
    95
    D3D10_1_LIBRARY_NOT_FOUND = -135,
moel@1
    96
    FUNCTION_NOT_FOUND = -136
moel@1
    97
  }  
moel@1
    98
moel@1
    99
  public enum NvThermalController {
moel@1
   100
    NONE = 0,
moel@1
   101
    GPU_INTERNAL,  
moel@1
   102
    ADM1032,
moel@1
   103
    MAX6649,       
moel@1
   104
    MAX1617,      
moel@1
   105
    LM99,      
moel@1
   106
    LM89,         
moel@1
   107
    LM64,         
moel@1
   108
    ADT7473,
moel@1
   109
    SBMAX6649,
moel@1
   110
    VBIOSEVT,  
moel@1
   111
    OS,    
moel@1
   112
    UNKNOWN = -1,
moel@1
   113
  } 
moel@1
   114
moel@1
   115
  public enum NvThermalTarget {
moel@1
   116
    NONE = 0,
moel@1
   117
    GPU = 1,
moel@1
   118
    MEMORY = 2,
moel@1
   119
    POWER_SUPPLY = 4,
moel@1
   120
    BOARD = 8,
moel@1
   121
    ALL = 15,
moel@1
   122
    UNKNOWN = -1
moel@1
   123
  };
moel@1
   124
moel@61
   125
  [StructLayout(LayoutKind.Sequential, Pack = 8)]
moel@1
   126
  public struct NvSensor {
moel@1
   127
    public NvThermalController Controller;
moel@1
   128
    public int DefaultMinTemp;
moel@1
   129
    public int DefaultMaxTemp;
moel@1
   130
    public int CurrentTemp;
moel@1
   131
    public NvThermalTarget Target;     
moel@1
   132
  }
moel@1
   133
moel@61
   134
  [StructLayout(LayoutKind.Sequential, Pack = 8)]
moel@1
   135
  public struct NvGPUThermalSettings {
moel@1
   136
    public int Version;
moel@1
   137
    public int Count;
moel@1
   138
    [MarshalAs(UnmanagedType.ByValArray, 
moel@1
   139
      SizeConst = NVAPI.MAX_THERMAL_SENSORS_PER_GPU)]
moel@1
   140
    public NvSensor[] Sensor;
moel@1
   141
  }
moel@1
   142
moel@61
   143
  [StructLayout(LayoutKind.Sequential)]
moel@1
   144
  public struct NvDisplayHandle {
moel@61
   145
    private IntPtr ptr;
moel@1
   146
  }
moel@1
   147
moel@61
   148
  [StructLayout(LayoutKind.Sequential)]
moel@1
   149
  public struct NvPhysicalGpuHandle {
moel@61
   150
    private IntPtr ptr;
moel@1
   151
  }
moel@1
   152
moel@1
   153
  public class NVAPI {
moel@1
   154
          
moel@1
   155
    private const int SHORT_STRING_MAX = 64;
moel@1
   156
moel@1
   157
    public const int MAX_THERMAL_SENSORS_PER_GPU = 3;
moel@1
   158
    public const int MAX_PHYSICAL_GPUS = 64;
moel@1
   159
    public static readonly int GPU_THERMAL_SETTINGS_VER =
moel@1
   160
      Marshal.SizeOf(typeof(NvGPUThermalSettings)) | 0x10000;
moel@1
   161
            
moel@1
   162
    private delegate IntPtr nvapi_QueryInterfaceDelegate(uint id);
moel@1
   163
    private delegate NvStatus NvAPI_InitializeDelegate();
moel@1
   164
    private delegate NvStatus NvAPI_GPU_GetFullNameDelegate(
moel@1
   165
      NvPhysicalGpuHandle gpuHandle, StringBuilder name);
moel@1
   166
moel@1
   167
    public delegate NvStatus NvAPI_GPU_GetThermalSettingsDelegate(
moel@1
   168
      NvPhysicalGpuHandle gpuHandle, int sensorIndex, 
moel@1
   169
      ref NvGPUThermalSettings nvGPUThermalSettings);
moel@1
   170
    public delegate NvStatus NvAPI_EnumNvidiaDisplayHandleDelegate(int thisEnum,
moel@1
   171
      ref NvDisplayHandle displayHandle);
moel@1
   172
    public delegate NvStatus NvAPI_GetPhysicalGPUsFromDisplayDelegate(
moel@1
   173
      NvDisplayHandle displayHandle, [Out] NvPhysicalGpuHandle[] gpuHandles, 
moel@1
   174
      out int gpuCount);
moel@1
   175
    public delegate NvStatus NvAPI_EnumPhysicalGPUsDelegate(
moel@1
   176
      [Out] NvPhysicalGpuHandle[] gpuHandles, out int gpuCount);
moel@38
   177
    public delegate NvStatus NvAPI_GPU_GetTachReadingDelegate(
moel@38
   178
      NvPhysicalGpuHandle gpuHandle, out int value);
moel@1
   179
moel@1
   180
    private static bool available = false;
moel@1
   181
    private static nvapi_QueryInterfaceDelegate nvapi_QueryInterface;
moel@1
   182
    private static NvAPI_InitializeDelegate NvAPI_Initialize;
moel@1
   183
    private static NvAPI_GPU_GetFullNameDelegate _NvAPI_GPU_GetFullName;
moel@1
   184
moel@1
   185
    public static NvAPI_GPU_GetThermalSettingsDelegate 
moel@1
   186
      NvAPI_GPU_GetThermalSettings;
moel@1
   187
    public static NvAPI_EnumNvidiaDisplayHandleDelegate
moel@1
   188
      NvAPI_EnumNvidiaDisplayHandle;
moel@1
   189
    public static NvAPI_GetPhysicalGPUsFromDisplayDelegate
moel@1
   190
      NvAPI_GetPhysicalGPUsFromDisplay;
moel@1
   191
    public static NvAPI_EnumPhysicalGPUsDelegate
moel@1
   192
      NvAPI_EnumPhysicalGPUs;
moel@38
   193
    public static NvAPI_GPU_GetTachReadingDelegate
moel@38
   194
      NvAPI_GPU_GetTachReading;
moel@1
   195
moel@1
   196
    public static NvStatus NvAPI_GPU_GetFullName(NvPhysicalGpuHandle gpuHandle,
moel@1
   197
      out string name) {
moel@1
   198
      StringBuilder builder = new StringBuilder(SHORT_STRING_MAX);
moel@1
   199
      NvStatus status = _NvAPI_GPU_GetFullName(gpuHandle, builder);
moel@1
   200
      name = builder.ToString();
moel@1
   201
      return status;
moel@1
   202
    }
moel@1
   203
moel@1
   204
    private static string GetDllName() {
moel@1
   205
      if (IntPtr.Size == 4) {
moel@1
   206
        return "nvapi.dll";
moel@1
   207
      } else {
moel@1
   208
        return "nvapi64.dll";
moel@1
   209
      }
moel@1
   210
    }
moel@1
   211
moel@1
   212
    private static void GetDelegate<T>(uint id, out T newDelegate) 
moel@1
   213
      where T : class 
moel@1
   214
    {
moel@1
   215
      IntPtr ptr = nvapi_QueryInterface(id);
moel@38
   216
      if (ptr != IntPtr.Zero) {
moel@38
   217
        newDelegate =
moel@38
   218
          Marshal.GetDelegateForFunctionPointer(ptr, typeof(T)) as T;
moel@38
   219
      } else {
moel@38
   220
        newDelegate = null;
moel@38
   221
      }
moel@1
   222
    }
moel@1
   223
moel@1
   224
    static NVAPI() { 
moel@1
   225
      DllImportAttribute attribute = new DllImportAttribute(GetDllName());
moel@1
   226
      attribute.CallingConvention = CallingConvention.Cdecl;
moel@1
   227
      attribute.PreserveSig = true;
moel@1
   228
      attribute.EntryPoint = "nvapi_QueryInterface";
moel@1
   229
      PInvokeDelegateFactory.CreateDelegate(attribute,
moel@1
   230
        out nvapi_QueryInterface);
moel@1
   231
moel@1
   232
      try {
moel@1
   233
        GetDelegate(0x0150E828, out NvAPI_Initialize);
moel@1
   234
      } catch (DllNotFoundException) { return; } 
moel@1
   235
        catch (ArgumentNullException) { return; }
moel@1
   236
moel@1
   237
      if (NvAPI_Initialize() == NvStatus.OK) {
moel@1
   238
        GetDelegate(0xE3640A56, out NvAPI_GPU_GetThermalSettings);
moel@1
   239
        GetDelegate(0xCEEE8E9F, out _NvAPI_GPU_GetFullName);
moel@1
   240
        GetDelegate(0x9ABDD40D, out NvAPI_EnumNvidiaDisplayHandle);
moel@1
   241
        GetDelegate(0x34EF9506, out NvAPI_GetPhysicalGPUsFromDisplay);
moel@1
   242
        GetDelegate(0xE5AC921F, out NvAPI_EnumPhysicalGPUs);
moel@38
   243
        GetDelegate(0x5F608315, out NvAPI_GPU_GetTachReading);        
moel@1
   244
        available = true;
moel@1
   245
      }
moel@1
   246
    }
moel@1
   247
moel@1
   248
    public static bool IsAvailable {
moel@1
   249
      get { return available; }
moel@1
   250
    }
moel@1
   251
moel@1
   252
  }
moel@1
   253
}