Hardware/ATI/ADL.cs
author moel.mich
Sat, 14 May 2011 13:26:09 +0000
changeset 280 2bc456906ad6
parent 200 50de2faf3336
child 333 c34cbcc7df66
permissions -rw-r--r--
Fixed the ATI GPU fan control. The settings now restore correctly to default settings (previously the "manual mode" was kept on some systems).
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.Runtime.InteropServices;
moel@1
    40
moel@1
    41
namespace OpenHardwareMonitor.Hardware.ATI {
moel@1
    42
  
moel@1
    43
  [StructLayout(LayoutKind.Sequential)]
moel@165
    44
  internal struct ADLAdapterInfo {
moel@1
    45
    public int Size;
moel@1
    46
    public int AdapterIndex;
moel@1
    47
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = ADL.ADL_MAX_PATH)]
moel@1
    48
    public string UDID;
moel@1
    49
    public int BusNumber;
moel@3
    50
    public int DeviceNumber;
moel@1
    51
    public int FunctionNumber;
moel@1
    52
    public int VendorID;
moel@1
    53
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = ADL.ADL_MAX_PATH)]
moel@1
    54
    public string AdapterName;
moel@1
    55
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = ADL.ADL_MAX_PATH)]
moel@1
    56
    public string DisplayName;
moel@1
    57
    public int Present;
moel@1
    58
    public int Exist;
moel@1
    59
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = ADL.ADL_MAX_PATH)]
moel@1
    60
    public string DriverPath;
moel@1
    61
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = ADL.ADL_MAX_PATH)]
moel@1
    62
    public string DriverPathExt;
moel@1
    63
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = ADL.ADL_MAX_PATH)]
moel@1
    64
    public string PNPString;
moel@1
    65
    public int OSDisplayIndex;
moel@1
    66
  }
moel@1
    67
moel@1
    68
  [StructLayout(LayoutKind.Sequential)]
moel@165
    69
  internal struct ADLPMActivity {
moel@1
    70
    public int Size;
moel@1
    71
    public int EngineClock;
moel@1
    72
    public int MemoryClock;
moel@1
    73
    public int Vddc;
moel@1
    74
    public int ActivityPercent;
moel@1
    75
    public int CurrentPerformanceLevel;
moel@1
    76
    public int CurrentBusSpeed;
moel@1
    77
    public int CurrentBusLanes;
moel@1
    78
    public int MaximumBusLanes;
moel@1
    79
    public int Reserved;
moel@1
    80
  }
moel@1
    81
moel@1
    82
  [StructLayout(LayoutKind.Sequential)]
moel@165
    83
  internal struct ADLTemperature {
moel@1
    84
    public int Size;
moel@1
    85
    public int Temperature;
moel@1
    86
  }
moel@1
    87
moel@1
    88
  [StructLayout(LayoutKind.Sequential)]
moel@165
    89
  internal struct ADLFanSpeedValue {
moel@1
    90
    public int Size;
moel@1
    91
    public int SpeedType;
moel@1
    92
    public int FanSpeed;
moel@1
    93
    public int Flags;
moel@1
    94
  }
moel@1
    95
moel@1
    96
  [StructLayout(LayoutKind.Sequential)]
moel@165
    97
  internal struct ADLFanSpeedInfo {
moel@1
    98
    public int Size;
moel@1
    99
    public int Flags;
moel@1
   100
    public int MinPercent;
moel@1
   101
    public int MaxPercent;
moel@1
   102
    public int MinRPM;
moel@1
   103
    public int MaxRPM;
moel@1
   104
  }
moel@1
   105
moel@165
   106
  internal class ADL {
moel@1
   107
    public const int ADL_MAX_PATH = 256;
moel@1
   108
    public const int ADL_MAX_ADAPTERS = 40;
moel@1
   109
    public const int ADL_MAX_DISPLAYS = 40;
moel@1
   110
    public const int ADL_MAX_DEVICENAME = 32;
moel@6
   111
    public const int ADL_OK = 0;
moel@15
   112
    public const int ADL_ERR = -1;
moel@1
   113
    public const int ADL_DRIVER_OK = 0;
moel@1
   114
    public const int ADL_MAX_GLSYNC_PORTS = 8;
moel@1
   115
    public const int ADL_MAX_GLSYNC_PORT_LEDS = 8;
moel@1
   116
    public const int ADL_MAX_NUM_DISPLAYMODES = 1024;
moel@1
   117
moel@1
   118
    public const int ADL_DL_FANCTRL_SPEED_TYPE_PERCENT = 1;
moel@1
   119
    public const int ADL_DL_FANCTRL_SPEED_TYPE_RPM = 2;
moel@1
   120
moel@1
   121
    public const int ADL_DL_FANCTRL_SUPPORTS_PERCENT_READ = 1;
moel@1
   122
    public const int ADL_DL_FANCTRL_SUPPORTS_PERCENT_WRITE = 2;
moel@1
   123
    public const int ADL_DL_FANCTRL_SUPPORTS_RPM_READ = 4;
moel@1
   124
    public const int ADL_DL_FANCTRL_SUPPORTS_RPM_WRITE = 8;
moel@247
   125
    public const int ADL_DL_FANCTRL_FLAG_USER_DEFINED_SPEED = 1;
moel@1
   126
moel@3
   127
    public const int ATI_VENDOR_ID1 = 1002;
moel@3
   128
    public const int ATI_VENDOR_ID2 = 0x1002;
moel@3
   129
moel@1
   130
    private delegate int ADL_Main_Control_CreateDelegate(
moel@1
   131
      ADL_Main_Memory_AllocDelegate callback, int enumConnectedAdapters);
moel@1
   132
    private delegate int ADL_Adapter_AdapterInfo_GetDelegate(IntPtr info,
moel@1
   133
      int size);
moel@1
   134
moel@1
   135
    public delegate int ADL_Main_Control_DestroyDelegate();
moel@1
   136
    public delegate int ADL_Adapter_NumberOfAdapters_GetDelegate(
moel@1
   137
      ref int numAdapters);    
moel@1
   138
    public delegate int ADL_Adapter_ID_GetDelegate(int adapterIndex,
moel@1
   139
      out int adapterID);
moel@12
   140
    public delegate int ADL_Display_AdapterID_GetDelegate(int adapterIndex,
moel@12
   141
      out int adapterID);      	
moel@1
   142
    public delegate int ADL_Adapter_Active_GetDelegate(int adapterIndex,
moel@1
   143
      out int status);
moel@1
   144
    public delegate int ADL_Overdrive5_CurrentActivity_GetDelegate(
moel@1
   145
      int iAdapterIndex, ref ADLPMActivity activity);
moel@1
   146
    public delegate int ADL_Overdrive5_Temperature_GetDelegate(int adapterIndex,
moel@1
   147
        int thermalControllerIndex, ref ADLTemperature temperature);
moel@1
   148
    public delegate int ADL_Overdrive5_FanSpeed_GetDelegate(int adapterIndex,
moel@1
   149
        int thermalControllerIndex, ref	ADLFanSpeedValue fanSpeedValue);
moel@1
   150
    public delegate int ADL_Overdrive5_FanSpeedInfo_GetDelegate(
moel@1
   151
      int adapterIndex, int thermalControllerIndex,
moel@1
   152
      ref ADLFanSpeedInfo fanSpeedInfo);
moel@247
   153
    public delegate int ADL_Overdrive5_FanSpeedToDefault_SetDelegate(
moel@247
   154
      int adapterIndex, int thermalControllerIndex);
moel@247
   155
    public delegate int ADL_Overdrive5_FanSpeed_SetDelegate(int adapterIndex,
moel@247
   156
      int thermalControllerIndex, ref	ADLFanSpeedValue fanSpeedValue);
moel@1
   157
moel@1
   158
    private static ADL_Main_Control_CreateDelegate
moel@1
   159
      _ADL_Main_Control_Create;
moel@1
   160
    private static ADL_Adapter_AdapterInfo_GetDelegate
moel@1
   161
      _ADL_Adapter_AdapterInfo_Get;
moel@1
   162
moel@167
   163
    public static ADL_Main_Control_DestroyDelegate
moel@1
   164
      ADL_Main_Control_Destroy;
moel@1
   165
    public static ADL_Adapter_NumberOfAdapters_GetDelegate
moel@1
   166
      ADL_Adapter_NumberOfAdapters_Get;
moel@12
   167
    public static ADL_Adapter_ID_GetDelegate 
moel@12
   168
      _ADL_Adapter_ID_Get;
moel@12
   169
    public static ADL_Display_AdapterID_GetDelegate 
moel@12
   170
      _ADL_Display_AdapterID_Get;
moel@12
   171
    public static ADL_Adapter_Active_GetDelegate 
moel@1
   172
      ADL_Adapter_Active_Get;
moel@1
   173
    public static ADL_Overdrive5_CurrentActivity_GetDelegate
moel@1
   174
      ADL_Overdrive5_CurrentActivity_Get;
moel@1
   175
    public static ADL_Overdrive5_Temperature_GetDelegate
moel@1
   176
      ADL_Overdrive5_Temperature_Get;
moel@1
   177
    public static ADL_Overdrive5_FanSpeed_GetDelegate
moel@1
   178
      ADL_Overdrive5_FanSpeed_Get;
moel@1
   179
    public static ADL_Overdrive5_FanSpeedInfo_GetDelegate
moel@1
   180
      ADL_Overdrive5_FanSpeedInfo_Get;
moel@247
   181
    public static ADL_Overdrive5_FanSpeedToDefault_SetDelegate
moel@247
   182
      ADL_Overdrive5_FanSpeedToDefault_Set;
moel@247
   183
    public static ADL_Overdrive5_FanSpeed_SetDelegate
moel@247
   184
      ADL_Overdrive5_FanSpeed_Set;
moel@1
   185
moel@8
   186
    private static string dllName;
moel@1
   187
moel@1
   188
    private static void GetDelegate<T>(string entryPoint, out T newDelegate)
moel@1
   189
      where T : class 
moel@1
   190
    {
moel@8
   191
      DllImportAttribute attribute = new DllImportAttribute(dllName);
moel@1
   192
      attribute.CallingConvention = CallingConvention.StdCall;
moel@1
   193
      attribute.PreserveSig = true;
moel@1
   194
      attribute.EntryPoint = entryPoint;
moel@1
   195
      PInvokeDelegateFactory.CreateDelegate(attribute, out newDelegate);
moel@1
   196
    }
moel@1
   197
moel@8
   198
    private static void CreateDelegates(string name) {
moel@195
   199
      int p = (int)Environment.OSVersion.Platform;
moel@8
   200
      if ((p == 4) || (p == 128))
moel@8
   201
        dllName = name + ".so";
moel@8
   202
      else
moel@8
   203
        dllName = name + ".dll";
moel@8
   204
moel@8
   205
      GetDelegate("ADL_Main_Control_Create",
moel@8
   206
        out _ADL_Main_Control_Create);
moel@8
   207
      GetDelegate("ADL_Adapter_AdapterInfo_Get",
moel@8
   208
        out _ADL_Adapter_AdapterInfo_Get);
moel@8
   209
      GetDelegate("ADL_Main_Control_Destroy",
moel@8
   210
        out ADL_Main_Control_Destroy);
moel@8
   211
      GetDelegate("ADL_Adapter_NumberOfAdapters_Get",
moel@8
   212
        out ADL_Adapter_NumberOfAdapters_Get);
moel@8
   213
      GetDelegate("ADL_Adapter_ID_Get",
moel@12
   214
        out _ADL_Adapter_ID_Get);
moel@12
   215
      GetDelegate("ADL_Display_AdapterID_Get", 
moel@12
   216
        out _ADL_Display_AdapterID_Get);
moel@8
   217
      GetDelegate("ADL_Adapter_Active_Get",
moel@8
   218
        out ADL_Adapter_Active_Get);
moel@8
   219
      GetDelegate("ADL_Overdrive5_CurrentActivity_Get",
moel@8
   220
        out ADL_Overdrive5_CurrentActivity_Get);
moel@8
   221
      GetDelegate("ADL_Overdrive5_Temperature_Get",
moel@8
   222
        out ADL_Overdrive5_Temperature_Get);
moel@8
   223
      GetDelegate("ADL_Overdrive5_FanSpeed_Get",
moel@8
   224
        out ADL_Overdrive5_FanSpeed_Get);
moel@8
   225
      GetDelegate("ADL_Overdrive5_FanSpeedInfo_Get",
moel@8
   226
        out ADL_Overdrive5_FanSpeedInfo_Get);
moel@247
   227
      GetDelegate("ADL_Overdrive5_FanSpeedToDefault_Set",
moel@247
   228
        out ADL_Overdrive5_FanSpeedToDefault_Set);
moel@247
   229
      GetDelegate("ADL_Overdrive5_FanSpeed_Set",
moel@247
   230
        out ADL_Overdrive5_FanSpeed_Set);
moel@8
   231
    }
moel@8
   232
moel@1
   233
    static ADL() {
moel@8
   234
      CreateDelegates("atiadlxx");
moel@1
   235
    }
moel@1
   236
moel@1
   237
    private ADL() { }
moel@1
   238
moel@1
   239
    public static int ADL_Main_Control_Create(int enumConnectedAdapters) {
moel@8
   240
      try {
moel@160
   241
        try {
moel@160
   242
          return _ADL_Main_Control_Create(Main_Memory_Alloc,
moel@160
   243
            enumConnectedAdapters);
moel@160
   244
        } catch {
moel@160
   245
          CreateDelegates("atiadlxy");
moel@160
   246
          return _ADL_Main_Control_Create(Main_Memory_Alloc,
moel@160
   247
            enumConnectedAdapters);
moel@160
   248
        }
moel@160
   249
      } catch {
moel@195
   250
        return ADL_ERR;
moel@8
   251
      }
moel@1
   252
    }
moel@1
   253
moel@1
   254
    public static int ADL_Adapter_AdapterInfo_Get(ADLAdapterInfo[] info) {
moel@1
   255
      int elementSize = Marshal.SizeOf(typeof(ADLAdapterInfo));
moel@1
   256
      int size = info.Length * elementSize;
moel@1
   257
      IntPtr ptr = Marshal.AllocHGlobal(size);
moel@1
   258
      int result = _ADL_Adapter_AdapterInfo_Get(ptr, size);
moel@1
   259
      for (int i = 0; i < info.Length; i++)
moel@1
   260
        info[i] = (ADLAdapterInfo)
moel@1
   261
          Marshal.PtrToStructure((IntPtr)((long)ptr + i * elementSize),
moel@1
   262
          typeof(ADLAdapterInfo));
moel@1
   263
      Marshal.FreeHGlobal(ptr);
moel@1
   264
      return result;
moel@1
   265
    }
moel@1
   266
moel@12
   267
    public static int ADL_Adapter_ID_Get(int adapterIndex,
moel@12
   268
      out int adapterID) {
moel@12
   269
      try {
moel@12
   270
        return _ADL_Adapter_ID_Get(adapterIndex, out adapterID);
moel@12
   271
      } catch (EntryPointNotFoundException) {
moel@12
   272
        try {
moel@12
   273
          return _ADL_Display_AdapterID_Get(adapterIndex, out adapterID);
moel@12
   274
        } catch (EntryPointNotFoundException) {
moel@12
   275
          adapterID = 1;
moel@12
   276
          return ADL_OK;
moel@12
   277
        }
moel@12
   278
      }
moel@12
   279
    }
moel@12
   280
moel@1
   281
    private delegate IntPtr ADL_Main_Memory_AllocDelegate(int size);
moel@1
   282
moel@200
   283
    // create a Main_Memory_Alloc delegate and keep it alive
moel@200
   284
    private static ADL_Main_Memory_AllocDelegate Main_Memory_Alloc =
moel@200
   285
      delegate(int size) {
moel@200
   286
        return Marshal.AllocHGlobal(size);
moel@200
   287
      };
moel@1
   288
moel@1
   289
    private static void Main_Memory_Free(IntPtr buffer) {
moel@1
   290
      if (IntPtr.Zero != buffer)
moel@1
   291
        Marshal.FreeHGlobal(buffer);
moel@1
   292
    }
moel@1
   293
  }
moel@1
   294
}