moel@1: /* moel@1: moel@344: This Source Code Form is subject to the terms of the Mozilla Public moel@344: License, v. 2.0. If a copy of the MPL was not distributed with this moel@344: file, You can obtain one at http://mozilla.org/MPL/2.0/. moel@344: moel@344: Copyright (C) 2009-2012 Michael Möller moel@344: Copyright (C) 2011 Christian Vallières moel@1: moel@1: */ moel@1: moel@1: using System; moel@1: using System.Runtime.InteropServices; moel@1: using System.Text; moel@1: moel@1: namespace OpenHardwareMonitor.Hardware.Nvidia { moel@1: moel@165: internal enum NvStatus { moel@1: OK = 0, moel@1: ERROR = -1, moel@1: LIBRARY_NOT_FOUND = -2, moel@1: NO_IMPLEMENTATION = -3, moel@1: API_NOT_INTIALIZED = -4, moel@1: INVALID_ARGUMENT = -5, moel@1: NVIDIA_DEVICE_NOT_FOUND = -6, moel@1: END_ENUMERATION = -7, moel@1: INVALID_HANDLE = -8, moel@1: INCOMPATIBLE_STRUCT_VERSION = -9, moel@1: HANDLE_INVALIDATED = -10, moel@1: OPENGL_CONTEXT_NOT_CURRENT = -11, moel@1: NO_GL_EXPERT = -12, moel@1: INSTRUMENTATION_DISABLED = -13, moel@1: EXPECTED_LOGICAL_GPU_HANDLE = -100, moel@1: EXPECTED_PHYSICAL_GPU_HANDLE = -101, moel@1: EXPECTED_DISPLAY_HANDLE = -102, moel@1: INVALID_COMBINATION = -103, moel@1: NOT_SUPPORTED = -104, moel@1: PORTID_NOT_FOUND = -105, moel@1: EXPECTED_UNATTACHED_DISPLAY_HANDLE = -106, moel@1: INVALID_PERF_LEVEL = -107, moel@1: DEVICE_BUSY = -108, moel@1: NV_PERSIST_FILE_NOT_FOUND = -109, moel@1: PERSIST_DATA_NOT_FOUND = -110, moel@1: EXPECTED_TV_DISPLAY = -111, moel@1: EXPECTED_TV_DISPLAY_ON_DCONNECTOR = -112, moel@1: NO_ACTIVE_SLI_TOPOLOGY = -113, moel@1: SLI_RENDERING_MODE_NOTALLOWED = -114, moel@1: EXPECTED_DIGITAL_FLAT_PANEL = -115, moel@1: ARGUMENT_EXCEED_MAX_SIZE = -116, moel@1: DEVICE_SWITCHING_NOT_ALLOWED = -117, moel@1: TESTING_CLOCKS_NOT_SUPPORTED = -118, moel@1: UNKNOWN_UNDERSCAN_CONFIG = -119, moel@1: TIMEOUT_RECONFIGURING_GPU_TOPO = -120, moel@1: DATA_NOT_FOUND = -121, moel@1: EXPECTED_ANALOG_DISPLAY = -122, moel@1: NO_VIDLINK = -123, moel@1: REQUIRES_REBOOT = -124, moel@1: INVALID_HYBRID_MODE = -125, moel@1: MIXED_TARGET_TYPES = -126, moel@1: SYSWOW64_NOT_SUPPORTED = -127, moel@1: IMPLICIT_SET_GPU_TOPOLOGY_CHANGE_NOT_ALLOWED = -128, moel@1: REQUEST_USER_TO_CLOSE_NON_MIGRATABLE_APPS = -129, moel@1: OUT_OF_MEMORY = -130, moel@1: WAS_STILL_DRAWING = -131, moel@1: FILE_NOT_FOUND = -132, moel@1: TOO_MANY_UNIQUE_STATE_OBJECTS = -133, moel@1: INVALID_CALL = -134, moel@1: D3D10_1_LIBRARY_NOT_FOUND = -135, moel@1: FUNCTION_NOT_FOUND = -136 moel@165: } moel@1: moel@165: internal enum NvThermalController { moel@1: NONE = 0, moel@309: GPU_INTERNAL, moel@1: ADM1032, moel@309: MAX6649, moel@309: MAX1617, moel@309: LM99, moel@309: LM89, moel@309: LM64, moel@1: ADT7473, moel@1: SBMAX6649, moel@309: VBIOSEVT, moel@309: OS, moel@1: UNKNOWN = -1, moel@165: } moel@1: moel@165: internal enum NvThermalTarget { moel@1: NONE = 0, moel@1: GPU = 1, moel@1: MEMORY = 2, moel@1: POWER_SUPPLY = 4, moel@1: BOARD = 8, moel@1: ALL = 15, moel@1: UNKNOWN = -1 moel@1: }; moel@1: moel@61: [StructLayout(LayoutKind.Sequential, Pack = 8)] moel@165: internal struct NvSensor { moel@1: public NvThermalController Controller; moel@140: public uint DefaultMinTemp; moel@140: public uint DefaultMaxTemp; moel@140: public uint CurrentTemp; moel@309: public NvThermalTarget Target; moel@1: } moel@1: moel@61: [StructLayout(LayoutKind.Sequential, Pack = 8)] moel@165: internal struct NvGPUThermalSettings { moel@140: public uint Version; moel@140: public uint Count; moel@309: [MarshalAs(UnmanagedType.ByValArray, moel@1: SizeConst = NVAPI.MAX_THERMAL_SENSORS_PER_GPU)] moel@1: public NvSensor[] Sensor; moel@1: } moel@1: moel@61: [StructLayout(LayoutKind.Sequential)] moel@165: internal struct NvDisplayHandle { moel@195: private readonly IntPtr ptr; moel@1: } moel@1: moel@61: [StructLayout(LayoutKind.Sequential)] moel@165: internal struct NvPhysicalGpuHandle { moel@195: private readonly IntPtr ptr; moel@1: } moel@1: moel@140: [StructLayout(LayoutKind.Sequential, Pack = 8)] moel@165: internal struct NvClocks { moel@140: public uint Version; moel@140: [MarshalAs(UnmanagedType.ByValArray, SizeConst = NVAPI.MAX_CLOCKS_PER_GPU)] moel@140: public uint[] Clock; moel@140: } moel@140: moel@140: [StructLayout(LayoutKind.Sequential, Pack = 8)] moel@165: internal struct NvPState { moel@140: public bool Present; moel@140: public int Percentage; moel@140: } moel@140: moel@140: [StructLayout(LayoutKind.Sequential, Pack = 8)] moel@165: internal struct NvPStates { moel@140: public uint Version; moel@140: public uint Flags; moel@140: [MarshalAs(UnmanagedType.ByValArray, SizeConst = NVAPI.MAX_PSTATES_PER_GPU)] moel@140: public NvPState[] PStates; moel@140: } moel@140: moel@140: [StructLayout(LayoutKind.Sequential, Pack = 8)] moel@165: internal struct NvUsages { moel@140: public uint Version; moel@140: [MarshalAs(UnmanagedType.ByValArray, SizeConst = NVAPI.MAX_USAGES_PER_GPU)] moel@140: public uint[] Usage; moel@140: } moel@140: moel@140: [StructLayout(LayoutKind.Sequential, Pack = 8)] moel@165: internal struct NvCooler { moel@140: public int Type; moel@140: public int Controller; moel@140: public int DefaultMin; moel@140: public int DefaultMax; moel@140: public int CurrentMin; moel@140: public int CurrentMax; moel@140: public int CurrentLevel; moel@140: public int DefaultPolicy; moel@140: public int CurrentPolicy; moel@140: public int Target; moel@140: public int ControlType; moel@140: public int Active; moel@140: } moel@140: moel@140: [StructLayout(LayoutKind.Sequential, Pack = 8)] moel@165: internal struct NvGPUCoolerSettings { moel@140: public uint Version; moel@140: public uint Count; moel@140: [MarshalAs(UnmanagedType.ByValArray, SizeConst = NVAPI.MAX_COOLER_PER_GPU)] moel@140: public NvCooler[] Cooler; moel@140: } moel@140: moel@140: [StructLayout(LayoutKind.Sequential, Pack = 8)] moel@309: internal struct NvLevel { moel@309: public int Level; moel@309: public int Policy; moel@309: } moel@309: moel@309: [StructLayout(LayoutKind.Sequential, Pack = 8)] moel@309: internal struct NvGPUCoolerLevels { moel@309: public uint Version; moel@309: [MarshalAs(UnmanagedType.ByValArray, SizeConst = NVAPI.MAX_COOLER_PER_GPU)] moel@309: public NvLevel[] Levels; moel@309: } moel@309: moel@309: [StructLayout(LayoutKind.Sequential, Pack = 8)] moel@165: internal struct NvMemoryInfo { moel@140: public uint Version; moel@309: [MarshalAs(UnmanagedType.ByValArray, SizeConst = moel@140: NVAPI.MAX_MEMORY_VALUES_PER_GPU)] moel@140: public uint[] Values; moel@140: } moel@140: moel@140: [StructLayout(LayoutKind.Sequential, Pack = 8)] moel@165: internal struct NvDisplayDriverVersion { moel@140: public uint Version; moel@140: public uint DriverVersion; moel@140: public uint BldChangeListNum; moel@140: [MarshalAs(UnmanagedType.ByValTStr, SizeConst = NVAPI.SHORT_STRING_MAX)] moel@140: public string BuildBranch; moel@140: [MarshalAs(UnmanagedType.ByValTStr, SizeConst = NVAPI.SHORT_STRING_MAX)] moel@140: public string Adapter; moel@165: } moel@140: moel@165: internal class NVAPI { moel@1: moel@1: public const int MAX_PHYSICAL_GPUS = 64; moel@140: public const int SHORT_STRING_MAX = 64; moel@140: moel@309: public const int MAX_THERMAL_SENSORS_PER_GPU = 3; moel@140: public const int MAX_CLOCKS_PER_GPU = 0x120; moel@140: public const int MAX_PSTATES_PER_GPU = 8; moel@140: public const int MAX_USAGES_PER_GPU = 33; moel@140: public const int MAX_COOLER_PER_GPU = 20; moel@140: public const int MAX_MEMORY_VALUES_PER_GPU = 5; moel@140: moel@140: public static readonly uint GPU_THERMAL_SETTINGS_VER = (uint) moel@1: Marshal.SizeOf(typeof(NvGPUThermalSettings)) | 0x10000; moel@140: public static readonly uint GPU_CLOCKS_VER = (uint) moel@140: Marshal.SizeOf(typeof(NvClocks)) | 0x20000; moel@140: public static readonly uint GPU_PSTATES_VER = (uint) moel@140: Marshal.SizeOf(typeof(NvPStates)) | 0x10000; moel@140: public static readonly uint GPU_USAGES_VER = (uint) moel@140: Marshal.SizeOf(typeof(NvUsages)) | 0x10000; moel@140: public static readonly uint GPU_COOLER_SETTINGS_VER = (uint) moel@140: Marshal.SizeOf(typeof(NvGPUCoolerSettings)) | 0x20000; moel@309: public static readonly uint GPU_MEMORY_INFO_VER = (uint) moel@140: Marshal.SizeOf(typeof(NvMemoryInfo)) | 0x20000; moel@140: public static readonly uint DISPLAY_DRIVER_VERSION_VER = (uint) moel@140: Marshal.SizeOf(typeof(NvDisplayDriverVersion)) | 0x10000; moel@309: public static readonly uint GPU_COOLER_LEVELS_VER = (uint) moel@309: Marshal.SizeOf(typeof(NvGPUCoolerLevels)) | 0x10000; moel@309: moel@1: private delegate IntPtr nvapi_QueryInterfaceDelegate(uint id); moel@1: private delegate NvStatus NvAPI_InitializeDelegate(); moel@1: private delegate NvStatus NvAPI_GPU_GetFullNameDelegate( moel@1: NvPhysicalGpuHandle gpuHandle, StringBuilder name); moel@1: moel@1: public delegate NvStatus NvAPI_GPU_GetThermalSettingsDelegate( moel@309: NvPhysicalGpuHandle gpuHandle, int sensorIndex, moel@1: ref NvGPUThermalSettings nvGPUThermalSettings); moel@1: public delegate NvStatus NvAPI_EnumNvidiaDisplayHandleDelegate(int thisEnum, moel@1: ref NvDisplayHandle displayHandle); moel@1: public delegate NvStatus NvAPI_GetPhysicalGPUsFromDisplayDelegate( moel@309: NvDisplayHandle displayHandle, [Out] NvPhysicalGpuHandle[] gpuHandles, moel@140: out uint gpuCount); moel@1: public delegate NvStatus NvAPI_EnumPhysicalGPUsDelegate( moel@1: [Out] NvPhysicalGpuHandle[] gpuHandles, out int gpuCount); moel@38: public delegate NvStatus NvAPI_GPU_GetTachReadingDelegate( moel@38: NvPhysicalGpuHandle gpuHandle, out int value); moel@140: public delegate NvStatus NvAPI_GPU_GetAllClocksDelegate( moel@140: NvPhysicalGpuHandle gpuHandle, ref NvClocks nvClocks); moel@140: public delegate NvStatus NvAPI_GPU_GetPStatesDelegate( moel@140: NvPhysicalGpuHandle gpuHandle, ref NvPStates nvPStates); moel@140: public delegate NvStatus NvAPI_GPU_GetUsagesDelegate( moel@140: NvPhysicalGpuHandle gpuHandle, ref NvUsages nvUsages); moel@140: public delegate NvStatus NvAPI_GPU_GetCoolerSettingsDelegate( moel@140: NvPhysicalGpuHandle gpuHandle, int coolerIndex, moel@140: ref NvGPUCoolerSettings nvGPUCoolerSettings); moel@309: public delegate NvStatus NvAPI_GPU_SetCoolerLevelsDelegate( moel@309: NvPhysicalGpuHandle gpuHandle, int coolerIndex, moel@309: ref NvGPUCoolerLevels NvGPUCoolerLevels); moel@140: public delegate NvStatus NvAPI_GPU_GetMemoryInfoDelegate( moel@140: NvDisplayHandle displayHandle, ref NvMemoryInfo nvMemoryInfo); moel@140: public delegate NvStatus NvAPI_GetDisplayDriverVersionDelegate( moel@140: NvDisplayHandle displayHandle, [In, Out] ref NvDisplayDriverVersion moel@140: nvDisplayDriverVersion); moel@140: public delegate NvStatus NvAPI_GetInterfaceVersionStringDelegate( moel@140: StringBuilder version); moel@334: public delegate NvStatus NvAPI_GPU_GetPCIIdentifiersDelegate( moel@334: NvPhysicalGpuHandle gpuHandle, out uint deviceId, out uint subSystemId, moel@334: out uint revisionId, out uint extDeviceId); moel@1: moel@195: private static readonly bool available; moel@195: private static readonly nvapi_QueryInterfaceDelegate nvapi_QueryInterface; moel@195: private static readonly NvAPI_InitializeDelegate NvAPI_Initialize; moel@309: private static readonly NvAPI_GPU_GetFullNameDelegate moel@195: _NvAPI_GPU_GetFullName; moel@195: private static readonly NvAPI_GetInterfaceVersionStringDelegate moel@140: _NvAPI_GetInterfaceVersionString; moel@1: moel@309: public static readonly NvAPI_GPU_GetThermalSettingsDelegate moel@1: NvAPI_GPU_GetThermalSettings; moel@140: public static readonly NvAPI_EnumNvidiaDisplayHandleDelegate moel@1: NvAPI_EnumNvidiaDisplayHandle; moel@140: public static readonly NvAPI_GetPhysicalGPUsFromDisplayDelegate moel@1: NvAPI_GetPhysicalGPUsFromDisplay; moel@140: public static readonly NvAPI_EnumPhysicalGPUsDelegate moel@1: NvAPI_EnumPhysicalGPUs; moel@140: public static readonly NvAPI_GPU_GetTachReadingDelegate moel@38: NvAPI_GPU_GetTachReading; moel@140: public static readonly NvAPI_GPU_GetAllClocksDelegate moel@140: NvAPI_GPU_GetAllClocks; moel@140: public static readonly NvAPI_GPU_GetPStatesDelegate moel@140: NvAPI_GPU_GetPStates; moel@140: public static readonly NvAPI_GPU_GetUsagesDelegate moel@140: NvAPI_GPU_GetUsages; moel@140: public static readonly NvAPI_GPU_GetCoolerSettingsDelegate moel@140: NvAPI_GPU_GetCoolerSettings; moel@309: public static readonly NvAPI_GPU_SetCoolerLevelsDelegate moel@309: NvAPI_GPU_SetCoolerLevels; moel@140: public static readonly NvAPI_GPU_GetMemoryInfoDelegate moel@140: NvAPI_GPU_GetMemoryInfo; moel@140: public static readonly NvAPI_GetDisplayDriverVersionDelegate moel@167: NvAPI_GetDisplayDriverVersion; moel@334: public static readonly NvAPI_GPU_GetPCIIdentifiersDelegate moel@334: NvAPI_GPU_GetPCIIdentifiers; moel@167: moel@167: private NVAPI() { } moel@1: moel@1: public static NvStatus NvAPI_GPU_GetFullName(NvPhysicalGpuHandle gpuHandle, moel@1: out string name) { moel@1: StringBuilder builder = new StringBuilder(SHORT_STRING_MAX); moel@101: NvStatus status; moel@101: if (_NvAPI_GPU_GetFullName != null) moel@101: status = _NvAPI_GPU_GetFullName(gpuHandle, builder); moel@101: else moel@101: status = NvStatus.FUNCTION_NOT_FOUND; moel@1: name = builder.ToString(); moel@1: return status; moel@1: } moel@1: moel@140: public static NvStatus NvAPI_GetInterfaceVersionString(out string version) { moel@140: StringBuilder builder = new StringBuilder(SHORT_STRING_MAX); moel@140: NvStatus status; moel@140: if (_NvAPI_GetInterfaceVersionString != null) moel@140: status = _NvAPI_GetInterfaceVersionString(builder); moel@140: else moel@140: status = NvStatus.FUNCTION_NOT_FOUND; moel@140: version = builder.ToString(); moel@140: return status; moel@140: } moel@140: moel@1: private static string GetDllName() { moel@1: if (IntPtr.Size == 4) { moel@1: return "nvapi.dll"; moel@1: } else { moel@1: return "nvapi64.dll"; moel@1: } moel@1: } moel@1: moel@309: private static void GetDelegate(uint id, out T newDelegate) moel@309: where T : class { moel@1: IntPtr ptr = nvapi_QueryInterface(id); moel@38: if (ptr != IntPtr.Zero) { moel@38: newDelegate = moel@38: Marshal.GetDelegateForFunctionPointer(ptr, typeof(T)) as T; moel@38: } else { moel@38: newDelegate = null; moel@38: } moel@1: } moel@1: moel@309: static NVAPI() { moel@1: DllImportAttribute attribute = new DllImportAttribute(GetDllName()); moel@1: attribute.CallingConvention = CallingConvention.Cdecl; moel@1: attribute.PreserveSig = true; moel@1: attribute.EntryPoint = "nvapi_QueryInterface"; moel@1: PInvokeDelegateFactory.CreateDelegate(attribute, moel@1: out nvapi_QueryInterface); moel@1: moel@1: try { moel@1: GetDelegate(0x0150E828, out NvAPI_Initialize); moel@1: } catch (DllNotFoundException) { return; } moel@121: catch (EntryPointNotFoundException) { return; } moel@1: catch (ArgumentNullException) { return; } moel@1: moel@1: if (NvAPI_Initialize() == NvStatus.OK) { moel@1: GetDelegate(0xE3640A56, out NvAPI_GPU_GetThermalSettings); moel@1: GetDelegate(0xCEEE8E9F, out _NvAPI_GPU_GetFullName); moel@1: GetDelegate(0x9ABDD40D, out NvAPI_EnumNvidiaDisplayHandle); moel@1: GetDelegate(0x34EF9506, out NvAPI_GetPhysicalGPUsFromDisplay); moel@1: GetDelegate(0xE5AC921F, out NvAPI_EnumPhysicalGPUs); moel@140: GetDelegate(0x5F608315, out NvAPI_GPU_GetTachReading); moel@140: GetDelegate(0x1BD69F49, out NvAPI_GPU_GetAllClocks); moel@140: GetDelegate(0x60DED2ED, out NvAPI_GPU_GetPStates); moel@140: GetDelegate(0x189A1FDF, out NvAPI_GPU_GetUsages); moel@140: GetDelegate(0xDA141340, out NvAPI_GPU_GetCoolerSettings); moel@309: GetDelegate(0x891FA0AE, out NvAPI_GPU_SetCoolerLevels); moel@140: GetDelegate(0x774AA982, out NvAPI_GPU_GetMemoryInfo); moel@140: GetDelegate(0xF951A4D1, out NvAPI_GetDisplayDriverVersion); moel@140: GetDelegate(0x01053FA5, out _NvAPI_GetInterfaceVersionString); moel@334: GetDelegate(0x2DDFB66E, out NvAPI_GPU_GetPCIIdentifiers); moel@140: moel@1: available = true; moel@1: } moel@1: } moel@1: moel@1: public static bool IsAvailable { moel@1: get { return available; } moel@1: } moel@1: moel@1: } moel@1: }