Fix ASUS Z170 EC temperature read returning zero values (#2153)
* Fix ASUS Z170 EC temperature read returning zero values Adjust EC read logic so temperature registers (PCH, T_SENSOR, VRM) return valid values on ASUS Z170 boards in user-mode. Verified with RWEverything and HWiNFO. * merge back to inter100, Use IBF clearing fallback when OBF unsupported * Fix formatting of CrOS enum entry * Update WindowsEmbeddedControllerIO.cs --------- Co-authored-by: PhyxionNL <7643972+PhyxionNL@users.noreply.github.com>
This commit is contained in:
@@ -391,6 +391,8 @@ internal class Identification
|
||||
return Model.ROG_ZENITH_II_EXTREME;
|
||||
case var _ when name.Equals("Z170-A", StringComparison.OrdinalIgnoreCase):
|
||||
return Model.Z170_A;
|
||||
case var _ when name.Equals("Z170 PRO GAMING", StringComparison.OrdinalIgnoreCase):
|
||||
return Model.Z170_PRO_GAMING;
|
||||
case var _ when name.Equals("B150M-C", StringComparison.OrdinalIgnoreCase):
|
||||
return Model.B150M_C;
|
||||
case var _ when name.Equals("B150M-C D3", StringComparison.OrdinalIgnoreCase):
|
||||
|
||||
@@ -257,6 +257,11 @@ public abstract class EmbeddedController : Hardware
|
||||
ECSensor.FanWaterPump,
|
||||
ECSensor.CurrCPU,
|
||||
ECSensor.VoltageCPU),
|
||||
new(Model.Z170_PRO_GAMING,
|
||||
BoardFamily.Intel100,
|
||||
ECSensor.TempChipset,
|
||||
ECSensor.TempVrm,
|
||||
ECSensor.TempTSensor),
|
||||
new(Model.PRIME_Z690_A,
|
||||
BoardFamily.Intel600,
|
||||
ECSensor.TempTSensor,
|
||||
@@ -398,6 +403,7 @@ public abstract class EmbeddedController : Hardware
|
||||
BoardFamily.Intel100, new Dictionary<ECSensor, EmbeddedControllerSource>
|
||||
{
|
||||
{ ECSensor.TempChipset, new EmbeddedControllerSource("Chipset", SensorType.Temperature, 0x003a) },
|
||||
{ ECSensor.TempVrm, new EmbeddedControllerSource("VRM", SensorType.Temperature, 0x003e) },
|
||||
{ ECSensor.TempTSensor, new EmbeddedControllerSource("T Sensor", SensorType.Temperature, 0x003d, blank: -40) },
|
||||
{ ECSensor.FanWaterPump, new EmbeddedControllerSource("Water Pump", SensorType.Fan, 0x00bc, 2) },
|
||||
{ ECSensor.CurrCPU, new EmbeddedControllerSource("CPU", SensorType.Current, 0x00f4) },
|
||||
|
||||
+72
-56
@@ -3,7 +3,6 @@
|
||||
// Copyright (C) LibreHardwareMonitor and Contributors.
|
||||
// All Rights Reserved.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Threading;
|
||||
using LibreHardwareMonitor.PawnIo;
|
||||
@@ -25,12 +24,12 @@ public class WindowsEmbeddedControllerIO : IEmbeddedControllerIO
|
||||
|
||||
// implementation
|
||||
private const int WaitSpins = 50;
|
||||
|
||||
private readonly LpcAcpiEc _pawnModule;
|
||||
private bool _disposed;
|
||||
|
||||
private int _waitReadFailures;
|
||||
|
||||
private readonly LpcAcpiEc _pawnModule;
|
||||
|
||||
public WindowsEmbeddedControllerIO()
|
||||
{
|
||||
_pawnModule = new LpcAcpiEc();
|
||||
@@ -62,22 +61,13 @@ public class WindowsEmbeddedControllerIO : IEmbeddedControllerIO
|
||||
{
|
||||
bank = SwitchBank(regBank);
|
||||
}
|
||||
|
||||
data[i] = ReadByte(regIndex);
|
||||
}
|
||||
|
||||
SwitchBank(prevBank);
|
||||
}
|
||||
|
||||
private byte ReadByte(byte register)
|
||||
{
|
||||
return ReadLoop<byte>(register, ReadByteOp);
|
||||
}
|
||||
|
||||
private void WriteByte(byte register, byte value)
|
||||
{
|
||||
WriteLoop(register, value, WriteByteOp);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (!_disposed)
|
||||
@@ -88,6 +78,16 @@ public class WindowsEmbeddedControllerIO : IEmbeddedControllerIO
|
||||
}
|
||||
}
|
||||
|
||||
private byte ReadByte(byte register)
|
||||
{
|
||||
return ReadLoop<byte>(register, ReadByteOp);
|
||||
}
|
||||
|
||||
private void WriteByte(byte register, byte value)
|
||||
{
|
||||
WriteLoop(register, value, WriteByteOp);
|
||||
}
|
||||
|
||||
private byte SwitchBank(byte bank)
|
||||
{
|
||||
byte previous = ReadByte(0xFF);
|
||||
@@ -145,10 +145,31 @@ public class WindowsEmbeddedControllerIO : IEmbeddedControllerIO
|
||||
return true;
|
||||
}
|
||||
|
||||
if (WaitForStatus(Status.OutputBufferFull, true))
|
||||
// Try OBF with reduced timeout
|
||||
for (int i = 0; i < MaxRetries; i++)
|
||||
{
|
||||
_waitReadFailures = 0;
|
||||
return true;
|
||||
byte status = ReadIOPort(Port.Command);
|
||||
if ((status & (byte)Status.OutputBufferFull) != 0)
|
||||
{
|
||||
_waitReadFailures = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
Thread.Sleep(1);
|
||||
}
|
||||
|
||||
// ASUS workaround: Wait for IBF to clear instead of OBF
|
||||
// Testing on Z170 Pro Gaming shows IBF clears in 1-3ms when data is ready
|
||||
for (int i = 0; i < WaitSpins; i++)
|
||||
{
|
||||
byte status = ReadIOPort(Port.Command);
|
||||
if ((status & (byte)Status.InputBufferFull) == 0)
|
||||
{
|
||||
_waitReadFailures = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
Thread.Sleep(1);
|
||||
}
|
||||
|
||||
_waitReadFailures++;
|
||||
@@ -170,45 +191,6 @@ public class WindowsEmbeddedControllerIO : IEmbeddedControllerIO
|
||||
_pawnModule.WritePort((byte)port, datum);
|
||||
}
|
||||
|
||||
public class BusMutexLockingFailedException : EmbeddedController.IOException
|
||||
{
|
||||
public BusMutexLockingFailedException()
|
||||
: base("could not lock ISA bus mutex")
|
||||
{ }
|
||||
}
|
||||
|
||||
private delegate bool ReadOp<TParam>(byte register, out TParam p);
|
||||
|
||||
private delegate bool WriteOp<in TParam>(byte register, TParam p);
|
||||
|
||||
// see the ACPI specification chapter 12
|
||||
private enum Port : byte
|
||||
{
|
||||
Command = 0x66,
|
||||
Data = 0x62
|
||||
}
|
||||
|
||||
private enum Command : byte
|
||||
{
|
||||
Read = 0x80, // RD_EC
|
||||
Write = 0x81, // WR_EC
|
||||
BurstEnable = 0x82, // BE_EC
|
||||
BurstDisable = 0x83, // BD_EC
|
||||
Query = 0x84 // QR_EC
|
||||
}
|
||||
|
||||
private enum Status : byte
|
||||
{
|
||||
OutputBufferFull = 0x01, // EC_OBF
|
||||
InputBufferFull = 0x02, // EC_IBF
|
||||
Command = 0x08, // CMD
|
||||
BurstMode = 0x10, // BURST
|
||||
SciEventPending = 0x20, // SCI_EVT
|
||||
SmiEventPending = 0x40 // SMI_EVT
|
||||
}
|
||||
|
||||
#region Read/Write ops
|
||||
|
||||
protected bool ReadByteOp(byte register, out byte value)
|
||||
{
|
||||
if (WaitWrite())
|
||||
@@ -250,5 +232,39 @@ public class WindowsEmbeddedControllerIO : IEmbeddedControllerIO
|
||||
return false;
|
||||
}
|
||||
|
||||
#endregion
|
||||
public class BusMutexLockingFailedException : EmbeddedController.IOException
|
||||
{
|
||||
public BusMutexLockingFailedException() : base("could not lock ISA bus mutex")
|
||||
{ }
|
||||
}
|
||||
|
||||
private delegate bool ReadOp<TParam>(byte register, out TParam p);
|
||||
|
||||
private delegate bool WriteOp<in TParam>(byte register, TParam p);
|
||||
|
||||
// see the ACPI specification chapter 12
|
||||
private enum Port : byte
|
||||
{
|
||||
Command = 0x66,
|
||||
Data = 0x62
|
||||
}
|
||||
|
||||
private enum Command : byte
|
||||
{
|
||||
Read = 0x80, // RD_EC
|
||||
Write = 0x81, // WR_EC
|
||||
BurstEnable = 0x82, // BE_EC
|
||||
BurstDisable = 0x83, // BD_EC
|
||||
Query = 0x84 // QR_EC
|
||||
}
|
||||
|
||||
private enum Status : byte
|
||||
{
|
||||
OutputBufferFull = 0x01, // EC_OBF
|
||||
InputBufferFull = 0x02, // EC_IBF
|
||||
Command = 0x08, // CMD
|
||||
BurstMode = 0x10, // BURST
|
||||
SciEventPending = 0x20, // SCI_EVT
|
||||
SmiEventPending = 0x40 // SMI_EVT
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,6 +115,7 @@ public enum Model
|
||||
TUF_X470_PLUS_GAMING,
|
||||
TUF_GAMING_X870_PLUS_WIFI,
|
||||
Z170_A,
|
||||
Z170_PRO_GAMING,
|
||||
B150M_C,
|
||||
B150M_C_D3,
|
||||
TUF_GAMING_X570_PLUS_WIFI,
|
||||
|
||||
Reference in New Issue
Block a user