Move mutexes out of Ring0
This commit is contained in:
@@ -487,6 +487,7 @@ public class Computer : IComputer
|
||||
_smbios = new SMBios();
|
||||
|
||||
Ring0.Open();
|
||||
Mutexes.Open();
|
||||
OpCode.Open();
|
||||
|
||||
AddGroups();
|
||||
@@ -628,6 +629,7 @@ public class Computer : IComputer
|
||||
OpCode.Close();
|
||||
InpOut.Close();
|
||||
Ring0.Close();
|
||||
Mutexes.Close();
|
||||
|
||||
_smbios = null;
|
||||
_open = false;
|
||||
|
||||
@@ -94,7 +94,7 @@ internal sealed class Amd0FCpu : AmdCpu
|
||||
{
|
||||
base.Update();
|
||||
|
||||
if (Ring0.WaitPciBusMutex(10))
|
||||
if (Mutexes.WaitPciBus(10))
|
||||
{
|
||||
if (_miscellaneousControlAddress != Interop.Ring0.INVALID_PCI_ADDRESS)
|
||||
{
|
||||
@@ -117,7 +117,7 @@ internal sealed class Amd0FCpu : AmdCpu
|
||||
}
|
||||
}
|
||||
|
||||
Ring0.ReleasePciBusMutex();
|
||||
Mutexes.ReleasePciBus();
|
||||
}
|
||||
|
||||
if (HasTimeStampCounter)
|
||||
|
||||
@@ -451,19 +451,19 @@ internal sealed class Amd10Cpu : AmdCpu
|
||||
|
||||
private static bool ReadSmuRegister(uint address, out uint value)
|
||||
{
|
||||
if (Ring0.WaitPciBusMutex(10))
|
||||
if (Mutexes.WaitPciBus(10))
|
||||
{
|
||||
if (!Ring0.WritePciConfig(0, 0xB8, address))
|
||||
{
|
||||
value = 0;
|
||||
|
||||
Ring0.ReleasePciBusMutex();
|
||||
Mutexes.ReleasePciBus();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool result = Ring0.ReadPciConfig(0, 0xBC, out value);
|
||||
|
||||
Ring0.ReleasePciBusMutex();
|
||||
Mutexes.ReleasePciBus();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -164,7 +164,7 @@ internal sealed class Amd17Cpu : AmdCpu
|
||||
uint smuSvi0TelPlane0 = 0;
|
||||
uint smuSvi0TelPlane1 = 0;
|
||||
|
||||
if (Ring0.WaitPciBusMutex(10))
|
||||
if (Mutexes.WaitPciBus(10))
|
||||
{
|
||||
// THM_TCON_CUR_TMP
|
||||
// CUR_TEMP [31:21]
|
||||
@@ -340,7 +340,7 @@ internal sealed class Amd17Cpu : AmdCpu
|
||||
}
|
||||
}
|
||||
|
||||
Ring0.ReleasePciBusMutex();
|
||||
Mutexes.ReleasePciBus();
|
||||
}
|
||||
|
||||
// voltage
|
||||
|
||||
@@ -30,7 +30,7 @@ public class WindowsEmbeddedControllerIO : IEmbeddedControllerIO
|
||||
|
||||
public WindowsEmbeddedControllerIO()
|
||||
{
|
||||
if (!Ring0.WaitEcMutex(10))
|
||||
if (!Mutexes.WaitEc(10))
|
||||
{
|
||||
throw new BusMutexLockingFailedException();
|
||||
}
|
||||
@@ -78,7 +78,7 @@ public class WindowsEmbeddedControllerIO : IEmbeddedControllerIO
|
||||
if (!_disposed)
|
||||
{
|
||||
_disposed = true;
|
||||
Ring0.ReleaseEcMutex();
|
||||
Mutexes.ReleaseEc();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -245,4 +245,4 @@ public class WindowsEmbeddedControllerIO : IEmbeddedControllerIO
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ internal class F718XX : ISuperIO
|
||||
if (index < 0 || index >= Controls.Length)
|
||||
throw new ArgumentOutOfRangeException(nameof(index));
|
||||
|
||||
if (!Ring0.WaitIsaBusMutex(10))
|
||||
if (!Mutexes.WaitIsaBus(10))
|
||||
return;
|
||||
|
||||
if (value.HasValue)
|
||||
@@ -66,7 +66,7 @@ internal class F718XX : ISuperIO
|
||||
RestoreDefaultFanPwmControl(index);
|
||||
}
|
||||
|
||||
Ring0.ReleaseIsaBusMutex();
|
||||
Mutexes.ReleaseIsaBus();
|
||||
}
|
||||
|
||||
public string GetReport()
|
||||
@@ -79,7 +79,7 @@ internal class F718XX : ISuperIO
|
||||
r.AppendLine(_address.ToString("X4", CultureInfo.InvariantCulture));
|
||||
r.AppendLine();
|
||||
|
||||
if (!Ring0.WaitIsaBusMutex(100))
|
||||
if (!Mutexes.WaitIsaBus(100))
|
||||
return r.ToString();
|
||||
|
||||
r.AppendLine("Hardware Monitor Registers");
|
||||
@@ -103,13 +103,13 @@ internal class F718XX : ISuperIO
|
||||
|
||||
r.AppendLine();
|
||||
|
||||
Ring0.ReleaseIsaBusMutex();
|
||||
Mutexes.ReleaseIsaBus();
|
||||
return r.ToString();
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
if (!Ring0.WaitIsaBusMutex(10))
|
||||
if (!Mutexes.WaitIsaBus(10))
|
||||
return;
|
||||
|
||||
for (int i = 0; i < Voltages.Length; i++)
|
||||
@@ -201,7 +201,7 @@ internal class F718XX : ISuperIO
|
||||
}
|
||||
}
|
||||
|
||||
Ring0.ReleaseIsaBusMutex();
|
||||
Mutexes.ReleaseIsaBus();
|
||||
}
|
||||
|
||||
private void SaveDefaultFanPwmControl(int index)
|
||||
|
||||
@@ -55,7 +55,7 @@ internal class GigabyteController
|
||||
|
||||
private bool AmdEnable(bool enabled)
|
||||
{
|
||||
if (!Ring0.WaitPciBusMutex(10))
|
||||
if (!Mutexes.WaitPciBus(10))
|
||||
return false;
|
||||
|
||||
// see D14F3x https://www.amd.com/system/files/TechDocs/55072_AMD_Family_15h_Models_70h-7Fh_BKDG.pdf
|
||||
@@ -99,7 +99,7 @@ internal class GigabyteController
|
||||
Ring0.WritePciConfig(amdIsaBridgeAddress, romAddressRange2Register, originalRomAddressRegister);
|
||||
}
|
||||
|
||||
Ring0.ReleasePciBusMutex();
|
||||
Mutexes.ReleasePciBus();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -257,7 +257,7 @@ internal class IT87XX : ISuperIO
|
||||
if (index < 0 || index >= Controls.Length)
|
||||
throw new ArgumentOutOfRangeException(nameof(index));
|
||||
|
||||
if (!Ring0.WaitIsaBusMutex(10))
|
||||
if (!Mutexes.WaitIsaBus(10))
|
||||
return;
|
||||
|
||||
if (value.HasValue)
|
||||
@@ -293,7 +293,7 @@ internal class IT87XX : ISuperIO
|
||||
RestoreDefaultFanPwmControl(index);
|
||||
}
|
||||
|
||||
Ring0.ReleaseIsaBusMutex();
|
||||
Mutexes.ReleaseIsaBus();
|
||||
}
|
||||
|
||||
public string GetReport()
|
||||
@@ -312,7 +312,7 @@ internal class IT87XX : ISuperIO
|
||||
r.AppendLine(_gpioAddress.ToString("X4", CultureInfo.InvariantCulture));
|
||||
r.AppendLine();
|
||||
|
||||
if (!Ring0.WaitIsaBusMutex(100))
|
||||
if (!Mutexes.WaitIsaBus(100))
|
||||
return r.ToString();
|
||||
|
||||
// dump memory of all banks if supported by chip
|
||||
@@ -361,7 +361,7 @@ internal class IT87XX : ISuperIO
|
||||
|
||||
r.AppendLine();
|
||||
r.AppendLine();
|
||||
Ring0.ReleaseIsaBusMutex();
|
||||
Mutexes.ReleaseIsaBus();
|
||||
return r.ToString();
|
||||
}
|
||||
|
||||
@@ -390,7 +390,7 @@ internal class IT87XX : ISuperIO
|
||||
|
||||
public void Update()
|
||||
{
|
||||
if (!Ring0.WaitIsaBusMutex(10))
|
||||
if (!Mutexes.WaitIsaBus(10))
|
||||
return;
|
||||
|
||||
for (int i = 0; i < Voltages.Length; i++)
|
||||
@@ -491,7 +491,7 @@ internal class IT87XX : ISuperIO
|
||||
}
|
||||
}
|
||||
|
||||
Ring0.ReleaseIsaBusMutex();
|
||||
Mutexes.ReleaseIsaBus();
|
||||
}
|
||||
|
||||
private byte ReadByte(byte register, out bool valid)
|
||||
|
||||
@@ -20,12 +20,12 @@ internal class LpcIO
|
||||
|
||||
public LpcIO(Motherboard motherboard)
|
||||
{
|
||||
if (!Ring0.IsOpen || !Ring0.WaitIsaBusMutex(100))
|
||||
if (!Ring0.IsOpen || !Mutexes.WaitIsaBus(100))
|
||||
return;
|
||||
|
||||
Detect(motherboard);
|
||||
|
||||
Ring0.ReleaseIsaBusMutex();
|
||||
Mutexes.ReleaseIsaBus();
|
||||
|
||||
if (Ipmi.IsBmcPresent())
|
||||
_superIOs.Add(new Ipmi(motherboard.Manufacturer));
|
||||
|
||||
@@ -362,7 +362,7 @@ internal class Nct677X : ISuperIO
|
||||
if (index < 0 || index >= Controls.Length)
|
||||
throw new ArgumentOutOfRangeException(nameof(index));
|
||||
|
||||
if (!Ring0.WaitIsaBusMutex(10))
|
||||
if (!Mutexes.WaitIsaBus(10))
|
||||
return;
|
||||
|
||||
if (value.HasValue)
|
||||
@@ -407,7 +407,7 @@ internal class Nct677X : ISuperIO
|
||||
RestoreDefaultFanControl(index);
|
||||
}
|
||||
|
||||
Ring0.ReleaseIsaBusMutex();
|
||||
Mutexes.ReleaseIsaBus();
|
||||
}
|
||||
|
||||
public void Update()
|
||||
@@ -415,7 +415,7 @@ internal class Nct677X : ISuperIO
|
||||
if (!_isNuvotonVendor)
|
||||
return;
|
||||
|
||||
if (!Ring0.WaitIsaBusMutex(10))
|
||||
if (!Mutexes.WaitIsaBus(10))
|
||||
return;
|
||||
|
||||
DisableIOSpaceLock();
|
||||
@@ -634,7 +634,7 @@ internal class Nct677X : ISuperIO
|
||||
}
|
||||
}
|
||||
|
||||
Ring0.ReleaseIsaBusMutex();
|
||||
Mutexes.ReleaseIsaBus();
|
||||
}
|
||||
|
||||
public string GetReport()
|
||||
@@ -651,7 +651,7 @@ internal class Nct677X : ISuperIO
|
||||
r.AppendLine(_port.ToString("X4", CultureInfo.InvariantCulture));
|
||||
r.AppendLine();
|
||||
|
||||
if (!Ring0.WaitIsaBusMutex(100))
|
||||
if (!Mutexes.WaitIsaBus(100))
|
||||
return r.ToString();
|
||||
|
||||
ushort[] addresses =
|
||||
@@ -799,7 +799,7 @@ internal class Nct677X : ISuperIO
|
||||
|
||||
r.AppendLine();
|
||||
|
||||
Ring0.ReleaseIsaBusMutex();
|
||||
Mutexes.ReleaseIsaBus();
|
||||
|
||||
return r.ToString();
|
||||
}
|
||||
|
||||
@@ -192,7 +192,7 @@ internal class W836XX : ISuperIO
|
||||
if (index < 0 || index >= Controls.Length)
|
||||
throw new ArgumentOutOfRangeException(nameof(index));
|
||||
|
||||
if (!Ring0.WaitIsaBusMutex(10))
|
||||
if (!Mutexes.WaitIsaBus(10))
|
||||
return;
|
||||
|
||||
if (value.HasValue)
|
||||
@@ -223,7 +223,7 @@ internal class W836XX : ISuperIO
|
||||
RestoreDefaultFanPwmControl(index);
|
||||
}
|
||||
|
||||
Ring0.ReleaseIsaBusMutex();
|
||||
Mutexes.ReleaseIsaBus();
|
||||
}
|
||||
|
||||
private void SaveDefaultFanPwmControl(int index) //added to save initial control values
|
||||
@@ -295,7 +295,7 @@ internal class W836XX : ISuperIO
|
||||
|
||||
public void Update()
|
||||
{
|
||||
if (!Ring0.WaitIsaBusMutex(10))
|
||||
if (!Mutexes.WaitIsaBus(10))
|
||||
return;
|
||||
|
||||
for (int i = 0; i < Voltages.Length; i++)
|
||||
@@ -397,7 +397,7 @@ internal class W836XX : ISuperIO
|
||||
Controls[i] = (float)Math.Round(value * 100.0f / 0xFF);
|
||||
}
|
||||
|
||||
Ring0.ReleaseIsaBusMutex();
|
||||
Mutexes.ReleaseIsaBus();
|
||||
}
|
||||
|
||||
public string GetReport()
|
||||
@@ -414,7 +414,7 @@ internal class W836XX : ISuperIO
|
||||
r.AppendLine(_address.ToString("X4", CultureInfo.InvariantCulture));
|
||||
r.AppendLine();
|
||||
|
||||
if (!Ring0.WaitIsaBusMutex(100))
|
||||
if (!Mutexes.WaitIsaBus(100))
|
||||
return r.ToString();
|
||||
|
||||
r.AppendLine("Hardware Monitor Registers");
|
||||
@@ -454,7 +454,7 @@ internal class W836XX : ISuperIO
|
||||
}
|
||||
|
||||
r.AppendLine();
|
||||
Ring0.ReleaseIsaBusMutex();
|
||||
Mutexes.ReleaseIsaBus();
|
||||
return r.ToString();
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
namespace LibreHardwareMonitor.Hardware;
|
||||
|
||||
internal static class Mutexes
|
||||
{
|
||||
private static Mutex _ecMutex;
|
||||
private static Mutex _isaBusMutex;
|
||||
private static Mutex _pciBusMutex;
|
||||
|
||||
/// <summary>
|
||||
/// Opens the mutexes.
|
||||
/// </summary>
|
||||
public static void Open()
|
||||
{
|
||||
_isaBusMutex = CreateOrOpenExistingMutex("Global\\Access_ISABUS.HTP.Method");
|
||||
_pciBusMutex = CreateOrOpenExistingMutex("Global\\Access_PCI");
|
||||
_ecMutex = CreateOrOpenExistingMutex("Global\\Access_EC");
|
||||
|
||||
static Mutex CreateOrOpenExistingMutex(string name)
|
||||
{
|
||||
try
|
||||
{
|
||||
return new Mutex(false, name);
|
||||
}
|
||||
catch (UnauthorizedAccessException)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Mutex.OpenExisting(name);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Ignored.
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Closes the mutexes.
|
||||
/// </summary>
|
||||
public static void Close()
|
||||
{
|
||||
_isaBusMutex?.Close();
|
||||
_pciBusMutex?.Close();
|
||||
_ecMutex?.Close();
|
||||
}
|
||||
|
||||
public static bool WaitIsaBus(int millisecondsTimeout)
|
||||
{
|
||||
return WaitMutex(_isaBusMutex, millisecondsTimeout);
|
||||
}
|
||||
|
||||
public static void ReleaseIsaBus()
|
||||
{
|
||||
_isaBusMutex?.ReleaseMutex();
|
||||
}
|
||||
|
||||
public static bool WaitPciBus(int millisecondsTimeout)
|
||||
{
|
||||
return WaitMutex(_pciBusMutex, millisecondsTimeout);
|
||||
}
|
||||
|
||||
public static void ReleasePciBus()
|
||||
{
|
||||
_pciBusMutex?.ReleaseMutex();
|
||||
}
|
||||
|
||||
public static bool WaitEc(int millisecondsTimeout)
|
||||
{
|
||||
return WaitMutex(_ecMutex, millisecondsTimeout);
|
||||
}
|
||||
|
||||
public static void ReleaseEc()
|
||||
{
|
||||
_ecMutex?.ReleaseMutex();
|
||||
}
|
||||
|
||||
private static bool WaitMutex(Mutex mutex, int millisecondsTimeout)
|
||||
{
|
||||
if (mutex == null)
|
||||
return true;
|
||||
|
||||
try
|
||||
{
|
||||
return mutex.WaitOne(millisecondsTimeout, false);
|
||||
}
|
||||
catch (AbandonedMutexException)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,6 @@
|
||||
// Partial Copyright (C) Michael Möller <mmoeller@openhardwaremonitor.org> and Contributors.
|
||||
// All Rights Reserved.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
@@ -18,10 +17,7 @@ namespace LibreHardwareMonitor.Hardware;
|
||||
internal static class Ring0
|
||||
{
|
||||
private static KernelDriver _driver;
|
||||
private static Mutex _ecMutex;
|
||||
private static string _filePath;
|
||||
private static Mutex _isaBusMutex;
|
||||
private static Mutex _pciBusMutex;
|
||||
|
||||
private static readonly StringBuilder _report = new();
|
||||
|
||||
@@ -92,24 +88,6 @@ internal static class Ring0
|
||||
|
||||
if (!_driver.IsOpen)
|
||||
_driver = null;
|
||||
|
||||
const string isaMutexName = "Global\\Access_ISABUS.HTP.Method";
|
||||
if (!TryCreateOrOpenExistingMutex(isaMutexName, out _isaBusMutex))
|
||||
{
|
||||
// Mutex could not be created or opened.
|
||||
}
|
||||
|
||||
const string pciMutexName = "Global\\Access_PCI";
|
||||
if (!TryCreateOrOpenExistingMutex(pciMutexName, out _pciBusMutex))
|
||||
{
|
||||
// Mutex could not be created or opened.
|
||||
}
|
||||
|
||||
const string ecMutexName = "Global\\Access_EC";
|
||||
if (!TryCreateOrOpenExistingMutex(ecMutexName, out _ecMutex))
|
||||
{
|
||||
// Mutex could not be created or opened.
|
||||
}
|
||||
}
|
||||
|
||||
private static bool Extract(string filePath)
|
||||
@@ -171,29 +149,6 @@ internal static class Ring0
|
||||
}
|
||||
}
|
||||
|
||||
private static bool TryCreateOrOpenExistingMutex(string name, out Mutex mutex)
|
||||
{
|
||||
try
|
||||
{
|
||||
mutex = new Mutex(false, name);
|
||||
return true;
|
||||
}
|
||||
catch (UnauthorizedAccessException)
|
||||
{
|
||||
try
|
||||
{
|
||||
mutex = Mutex.OpenExisting(name);
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
mutex = null;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void Delete()
|
||||
{
|
||||
try
|
||||
@@ -338,24 +293,6 @@ internal static class Ring0
|
||||
_driver = null;
|
||||
}
|
||||
|
||||
if (_isaBusMutex != null)
|
||||
{
|
||||
_isaBusMutex.Close();
|
||||
_isaBusMutex = null;
|
||||
}
|
||||
|
||||
if (_pciBusMutex != null)
|
||||
{
|
||||
_pciBusMutex.Close();
|
||||
_pciBusMutex = null;
|
||||
}
|
||||
|
||||
if (_ecMutex != null)
|
||||
{
|
||||
_ecMutex.Close();
|
||||
_ecMutex = null;
|
||||
}
|
||||
|
||||
// try to delete temporary driver file again if failed during open
|
||||
Delete();
|
||||
}
|
||||
@@ -375,78 +312,6 @@ internal static class Ring0
|
||||
return null;
|
||||
}
|
||||
|
||||
public static bool WaitIsaBusMutex(int millisecondsTimeout)
|
||||
{
|
||||
if (_isaBusMutex == null)
|
||||
return true;
|
||||
|
||||
try
|
||||
{
|
||||
return _isaBusMutex.WaitOne(millisecondsTimeout, false);
|
||||
}
|
||||
catch (AbandonedMutexException)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static void ReleaseIsaBusMutex()
|
||||
{
|
||||
_isaBusMutex?.ReleaseMutex();
|
||||
}
|
||||
|
||||
public static bool WaitPciBusMutex(int millisecondsTimeout)
|
||||
{
|
||||
if (_pciBusMutex == null)
|
||||
return true;
|
||||
|
||||
try
|
||||
{
|
||||
return _pciBusMutex.WaitOne(millisecondsTimeout, false);
|
||||
}
|
||||
catch (AbandonedMutexException)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static void ReleasePciBusMutex()
|
||||
{
|
||||
_pciBusMutex?.ReleaseMutex();
|
||||
}
|
||||
|
||||
public static bool WaitEcMutex(int millisecondsTimeout)
|
||||
{
|
||||
if (_ecMutex == null)
|
||||
return true;
|
||||
|
||||
try
|
||||
{
|
||||
return _ecMutex.WaitOne(millisecondsTimeout, false);
|
||||
}
|
||||
catch (AbandonedMutexException)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static void ReleaseEcMutex()
|
||||
{
|
||||
_ecMutex?.ReleaseMutex();
|
||||
}
|
||||
|
||||
public static bool ReadMsr(uint index, out uint eax, out uint edx)
|
||||
{
|
||||
if (_driver == null)
|
||||
|
||||
@@ -700,12 +700,12 @@ internal class RyzenSMU
|
||||
|
||||
private static void WriteReg(uint addr, uint data)
|
||||
{
|
||||
if (Ring0.WaitPciBusMutex(10))
|
||||
if (Mutexes.WaitPciBus(10))
|
||||
{
|
||||
if (Ring0.WritePciConfig(0x00, SMU_PCI_ADDR_REG, addr))
|
||||
Ring0.WritePciConfig(0x00, SMU_PCI_DATA_REG, data);
|
||||
|
||||
Ring0.ReleasePciBusMutex();
|
||||
Mutexes.ReleasePciBus();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -713,12 +713,12 @@ internal class RyzenSMU
|
||||
{
|
||||
bool read = false;
|
||||
|
||||
if (Ring0.WaitPciBusMutex(10))
|
||||
if (Mutexes.WaitPciBus(10))
|
||||
{
|
||||
if (Ring0.WritePciConfig(0x00, SMU_PCI_ADDR_REG, addr))
|
||||
read = Ring0.ReadPciConfig(0x00, SMU_PCI_DATA_REG, out data);
|
||||
|
||||
Ring0.ReleasePciBusMutex();
|
||||
Mutexes.ReleasePciBus();
|
||||
}
|
||||
|
||||
return read;
|
||||
|
||||
Reference in New Issue
Block a user