moel@1: /*
moel@1:   
moel@1:   Version: MPL 1.1/GPL 2.0/LGPL 2.1
moel@1: 
moel@1:   The contents of this file are subject to the Mozilla Public License Version
moel@1:   1.1 (the "License"); you may not use this file except in compliance with
moel@1:   the License. You may obtain a copy of the License at
moel@1:  
moel@1:   http://www.mozilla.org/MPL/
moel@1: 
moel@1:   Software distributed under the License is distributed on an "AS IS" basis,
moel@1:   WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
moel@1:   for the specific language governing rights and limitations under the License.
moel@1: 
moel@1:   The Original Code is the Open Hardware Monitor code.
moel@1: 
moel@1:   The Initial Developer of the Original Code is 
moel@1:   Michael Möller <m.moeller@gmx.ch>.
moel@1:   Portions created by the Initial Developer are Copyright (C) 2009-2010
moel@1:   the Initial Developer. All Rights Reserved.
moel@1: 
moel@1:   Contributor(s):
moel@1: 
moel@1:   Alternatively, the contents of this file may be used under the terms of
moel@1:   either the GNU General Public License Version 2 or later (the "GPL"), or
moel@1:   the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
moel@1:   in which case the provisions of the GPL or the LGPL are applicable instead
moel@1:   of those above. If you wish to allow use of your version of this file only
moel@1:   under the terms of either the GPL or the LGPL, and not to allow others to
moel@1:   use your version of this file under the terms of the MPL, indicate your
moel@1:   decision by deleting the provisions above and replace them with the notice
moel@1:   and other provisions required by the GPL or the LGPL. If you do not delete
moel@1:   the provisions above, a recipient may use your version of this file under
moel@1:   the terms of any one of the MPL, the GPL or the LGPL.
moel@1:  
moel@1: */
moel@1: 
moel@1: using System;
moel@1: using System.Runtime.InteropServices;
moel@162: using System.Threading;
moel@1: 
moel@1: namespace OpenHardwareMonitor.Hardware {
moel@1: 
moel@165:   internal class WinRing0 {
moel@167: 
moel@167:     private WinRing0() { }
moel@1:     
moel@1:     public enum OlsDllStatus{
moel@1:       OLS_DLL_NO_ERROR                        = 0,
moel@1:       OLS_DLL_UNSUPPORTED_PLATFORM            = 1,
moel@1:       OLS_DLL_DRIVER_NOT_LOADED               = 2,
moel@1:       OLS_DLL_DRIVER_NOT_FOUND                = 3,
moel@1:       OLS_DLL_DRIVER_UNLOADED                 = 4,
moel@1:       OLS_DLL_DRIVER_NOT_LOADED_ON_NETWORK    = 5,
moel@1:       OLS_DLL_UNKNOWN_ERROR                   = 9
moel@1:     }
moel@1: 
moel@1:     private static bool available = false;
moel@167:     private static Mutex isaBusMutex;
moel@1: 
moel@1:     private static string GetDllName() {   
moel@1:       int p = (int)System.Environment.OSVersion.Platform;
moel@1:       if ((p == 4) || (p == 128)) {
moel@1:         if (IntPtr.Size == 4) {
moel@1:           return "libring0.so";
moel@1:         } else {
moel@1:           return "libring0x64.so";
moel@1:         }
moel@1:       } else {
moel@1:         if (IntPtr.Size == 4) {
moel@1:           return "WinRing0.dll";
moel@1:         } else {
moel@1:           return "WinRing0x64.dll";
moel@1:         }
moel@1:       }                       
moel@1:     }
moel@1:     
moel@1:     private delegate bool InitializeOlsDelegate();
moel@1:     private delegate void DeinitializeOlsDelegate();
moel@1:     
moel@1:     public delegate bool IsCpuidDelegate();
moel@90:     public delegate bool CpuidTxDelegate(uint index, uint ecxValue,
moel@90:       out uint eax, out uint ebx, out uint ecx, out uint edx,
moel@90:       UIntPtr threadAffinityMask);
moel@46:     public delegate bool RdmsrDelegate(uint index, out uint eax, out uint edx);
moel@46:     public delegate bool RdmsrTxDelegate(uint index, out uint eax, out uint edx,
moel@46:       UIntPtr threadAffinityMask);
moel@1:     public delegate byte ReadIoPortByteDelegate(ushort port);
moel@1:     public delegate void WriteIoPortByteDelegate(ushort port, byte value);
moel@1:     public delegate uint FindPciDeviceByIdDelegate(ushort vendorId, 
moel@1:       ushort deviceId, byte index);
moel@1:     public delegate bool ReadPciConfigDwordExDelegate(uint pciAddress, 
moel@1:       uint regAddress, out uint value);
moel@14:     public delegate bool WritePciConfigDwordExDelegate(uint pciAddress, 
moel@14:       uint regAddress, uint value);
moel@46:     public delegate bool RdtscTxDelegate(out uint eax, out uint edx,
moel@46:       UIntPtr threadAffinityMask);
moel@79:     public delegate bool RdtscDelegate(out uint eax, out uint edx);
moel@1: 
moel@167:     private static InitializeOlsDelegate InitializeOls = 
moel@167:       CreateDelegate<InitializeOlsDelegate>("InitializeOls");
moel@167:     private static DeinitializeOlsDelegate DeinitializeOls =
moel@167:       CreateDelegate<DeinitializeOlsDelegate>("DeinitializeOls");
moel@1: 
moel@167:     public static readonly IsCpuidDelegate IsCpuid =
moel@167:       CreateDelegate<IsCpuidDelegate>("IsCpuid");
moel@167:     public static readonly CpuidTxDelegate CpuidTx =
moel@167:       CreateDelegate<CpuidTxDelegate>("CpuidTx");
moel@167:     public static readonly RdmsrDelegate Rdmsr =
moel@167:       CreateDelegate<RdmsrDelegate>("Rdmsr");
moel@167:     public static readonly RdmsrTxDelegate RdmsrTx =
moel@167:       CreateDelegate<RdmsrTxDelegate>("RdmsrTx");
moel@167:     public static readonly ReadIoPortByteDelegate ReadIoPortByte =
moel@167:       CreateDelegate<ReadIoPortByteDelegate>("ReadIoPortByte");
moel@167:     public static readonly WriteIoPortByteDelegate WriteIoPortByte =
moel@167:       CreateDelegate<WriteIoPortByteDelegate>("WriteIoPortByte");
moel@167:     public static readonly FindPciDeviceByIdDelegate FindPciDeviceById =
moel@167:       CreateDelegate<FindPciDeviceByIdDelegate>("FindPciDeviceById");
moel@167:     public static readonly ReadPciConfigDwordExDelegate ReadPciConfigDwordEx =
moel@167:       CreateDelegate<ReadPciConfigDwordExDelegate>("ReadPciConfigDwordEx");
moel@167:     public static readonly WritePciConfigDwordExDelegate WritePciConfigDwordEx =
moel@167:       CreateDelegate<WritePciConfigDwordExDelegate>("WritePciConfigDwordEx");
moel@167:     public static readonly RdtscTxDelegate RdtscTx =
moel@167:       CreateDelegate<RdtscTxDelegate>("RdtscTx");
moel@167:     public static readonly RdtscDelegate Rdtsc =
moel@167:       CreateDelegate<RdtscDelegate>("Rdtsc");
moel@167:  
moel@167:     private static T CreateDelegate<T>(string entryPoint) where T : class {
moel@1:       DllImportAttribute attribute = new DllImportAttribute(GetDllName());
moel@1:       attribute.CallingConvention = CallingConvention.Winapi;
moel@1:       attribute.PreserveSig = true;
moel@1:       attribute.EntryPoint = entryPoint;
moel@1:       attribute.CharSet = CharSet.Auto;
moel@167:       T result;
moel@167:       PInvokeDelegateFactory.CreateDelegate(attribute, out result);
moel@167:       return result;
moel@1:     }
moel@1: 
moel@167:     public static void Open() {
moel@1:       try {
moel@1:         if (InitializeOls != null && InitializeOls())
moel@1:           available = true;
moel@167:       } catch (DllNotFoundException) { }   
moel@167:       
moel@162:       isaBusMutex = new Mutex(false, "Access_ISABUS.HTP.Method");
moel@1:     }
moel@167: 
moel@1:     public static bool IsAvailable {
moel@1:       get { return available; }
moel@1:     }
moel@1: 
moel@167:     public static void Close() {
moel@167:       if (available)
moel@167:         DeinitializeOls();        
moel@167:       isaBusMutex.Close();      
moel@167:     }    
moel@167: 
moel@163:     public static bool WaitIsaBusMutex(int millisecondsTimeout) {
moel@162:       try {
moel@167:         return isaBusMutex.WaitOne(millisecondsTimeout, false);
moel@167:       } catch (AbandonedMutexException) { return false; } 
moel@167:         catch (InvalidOperationException) { return false; }     
moel@162:     }
moel@162: 
moel@162:     public static void ReleaseIsaBusMutex() {
moel@162:       isaBusMutex.ReleaseMutex();
moel@167:     }    
moel@1:   }
moel@1: }