Skip to content

Commit a943439

Browse files
committed
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.
1 parent 77d4379 commit a943439

4 files changed

Lines changed: 81 additions & 69 deletions

File tree

OpenHardwareMonitorLib/Hardware/Motherboard/Identification.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,8 @@ public static Model GetModel(string name)
383383
return Model.ROG_ZENITH_II_EXTREME;
384384
case var _ when name.Equals("Z170-A", StringComparison.OrdinalIgnoreCase):
385385
return Model.Z170_A;
386+
case var _ when name.Equals("Z170 PRO GAMING", StringComparison.OrdinalIgnoreCase):
387+
return Model.Z170_PRO_GAMING;
386388
case var _ when name.Equals("B150M-C", StringComparison.OrdinalIgnoreCase):
387389
return Model.B150M_C;
388390
case var _ when name.Equals("B150M-C D3", StringComparison.OrdinalIgnoreCase):

OpenHardwareMonitorLib/Hardware/Motherboard/Lpc/EC/EmbeddedController.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,11 @@ public abstract class EmbeddedController : Hardware
252252
ECSensor.FanWaterPump,
253253
ECSensor.CurrCPU,
254254
ECSensor.VoltageCPU),
255+
new(Model.Z170_PRO_GAMING,
256+
BoardFamily.Intel100,
257+
ECSensor.TempChipset,
258+
ECSensor.TempVrm,
259+
ECSensor.TempTSensor),
255260
new(Model.PRIME_Z690_A,
256261
BoardFamily.Intel600,
257262
ECSensor.TempTSensor,
@@ -351,6 +356,7 @@ public abstract class EmbeddedController : Hardware
351356
BoardFamily.Intel100, new Dictionary<ECSensor, EmbeddedControllerSource>
352357
{
353358
{ ECSensor.TempChipset, new EmbeddedControllerSource("Chipset", SensorType.Temperature, 0x003a) },
359+
{ ECSensor.TempVrm, new EmbeddedControllerSource("VRM", SensorType.Temperature, 0x003e) },
354360
{ ECSensor.TempTSensor, new EmbeddedControllerSource("T Sensor", SensorType.Temperature, 0x003d, blank: -40) },
355361
{ ECSensor.FanWaterPump, new EmbeddedControllerSource("Water Pump", SensorType.Fan, 0x00bc, 2) },
356362
{ ECSensor.CurrCPU, new EmbeddedControllerSource("CPU", SensorType.Current, 0x00f4) },

OpenHardwareMonitorLib/Hardware/Motherboard/Lpc/EC/WindowsEmbeddedControllerIO.cs

Lines changed: 72 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
using System;
2-
using System.Diagnostics;
1+
using System.Diagnostics;
32
using System.Threading;
43

54
namespace OpenHardwareMonitor.Hardware.Motherboard.Lpc.EC;
@@ -17,7 +16,7 @@ public class WindowsEmbeddedControllerIO : IEmbeddedControllerIO
1716
private const int FailuresBeforeSkip = 20;
1817
private const int MaxRetries = 5;
1918

20-
// implementation
19+
// implementation
2120
private const int WaitSpins = 50;
2221
private bool _disposed;
2322

@@ -33,7 +32,7 @@ public WindowsEmbeddedControllerIO()
3332

3433
public void Read(ushort[] registers, byte[] data)
3534
{
36-
Trace.Assert(registers.Length <= data.Length,
35+
Trace.Assert(registers.Length <= data.Length,
3736
"data buffer length has to be greater or equal to the registers array length");
3837

3938
byte bank = 0;
@@ -58,15 +57,8 @@ public void Read(ushort[] registers, byte[] data)
5857
SwitchBank(prevBank);
5958
}
6059

61-
private byte ReadByte(byte register)
62-
{
63-
return ReadLoop<byte>(register, ReadByteOp);
64-
}
65-
66-
private void WriteByte(byte register, byte value)
67-
{
68-
WriteLoop(register, value, WriteByteOp);
69-
}
60+
private byte ReadByte(byte register) => ReadLoop<byte>(register, ReadByteOp);
61+
private void WriteByte(byte register, byte value) => WriteLoop(register, value, WriteByteOp);
7062

7163
public void Dispose()
7264
{
@@ -84,7 +76,7 @@ private byte SwitchBank(byte bank)
8476
return previous;
8577
}
8678

87-
private TResult ReadLoop<TResult>(byte register, ReadOp<TResult> op) where TResult : new()
79+
private static TResult ReadLoop<TResult>(byte register, ReadOp<TResult> op) where TResult : new()
8880
{
8981
TResult result = new();
9082

@@ -99,7 +91,7 @@ private byte SwitchBank(byte bank)
9991
return result;
10092
}
10193

102-
private void WriteLoop<TValue>(byte register, TValue value, WriteOp<TValue> op)
94+
private static void WriteLoop<TValue>(byte register, TValue value, WriteOp<TValue> op)
10395
{
10496
for (int i = 0; i < MaxRetries; i++)
10597
{
@@ -110,11 +102,11 @@ private void WriteLoop<TValue>(byte register, TValue value, WriteOp<TValue> op)
110102
}
111103
}
112104

113-
private bool WaitForStatus(Status status, bool isSet)
105+
private static bool WaitForStatus(Status status, bool isSet)
114106
{
115107
for (int i = 0; i < WaitSpins; i++)
116108
{
117-
byte value = ReadIOPort(Port.Command);
109+
byte value = ReadIoPort(Port.Command);
118110

119111
if (((byte)status & (!isSet ? value : (byte)~value)) == 0)
120112
{
@@ -134,10 +126,31 @@ private bool WaitRead()
134126
return true;
135127
}
136128

137-
if (WaitForStatus(Status.OutputBufferFull, true))
129+
// Try OBF with reduced timeout
130+
for (int i = 0; i < MaxRetries; i++)
138131
{
139-
_waitReadFailures = 0;
140-
return true;
132+
byte status = ReadIoPort(Port.Command);
133+
if ((status & (byte)Status.OutputBufferFull) != 0)
134+
{
135+
_waitReadFailures = 0;
136+
return true;
137+
}
138+
139+
Thread.Sleep(1);
140+
}
141+
142+
// ASUS workaround: Wait for IBF to clear instead of OBF
143+
// Testing on Z170 Pro Gaming shows IBF clears in 1-3ms when data is ready
144+
for (int i = 0; i < WaitSpins; i++)
145+
{
146+
byte status = ReadIoPort(Port.Command);
147+
if ((status & (byte)Status.InputBufferFull) == 0)
148+
{
149+
_waitReadFailures = 0;
150+
return true;
151+
}
152+
153+
Thread.Sleep(1);
141154
}
142155

143156
_waitReadFailures++;
@@ -149,14 +162,49 @@ private bool WaitWrite()
149162
return WaitForStatus(Status.InputBufferFull, false);
150163
}
151164

152-
private byte ReadIOPort(Port port)
165+
private static byte ReadIoPort(Port port) => Ring0.ReadIoPort((byte)port);
166+
167+
private static void WriteIoPort(Port port, byte datum) => Ring0.WriteIoPort((byte)port, datum);
168+
169+
protected bool ReadByteOp(byte register, out byte value)
153170
{
154-
return Ring0.ReadIoPort((uint)port);
171+
if (WaitWrite())
172+
{
173+
WriteIoPort(Port.Command, (byte)Command.Read);
174+
175+
if (WaitWrite())
176+
{
177+
WriteIoPort(Port.Data, register);
178+
179+
if (WaitWrite() && WaitRead())
180+
{
181+
value = ReadIoPort(Port.Data);
182+
return true;
183+
}
184+
}
185+
}
186+
187+
value = 0;
188+
return false;
155189
}
156190

157-
private void WriteIOPort(Port port, byte datum)
191+
protected bool WriteByteOp(byte register, byte value)
158192
{
159-
Ring0.WriteIoPort((uint)port, datum);
193+
if (WaitWrite())
194+
{
195+
WriteIoPort(Port.Command, (byte)Command.Write);
196+
if (WaitWrite())
197+
{
198+
WriteIoPort(Port.Data, register);
199+
if (WaitWrite())
200+
{
201+
WriteIoPort(Port.Data, value);
202+
return true;
203+
}
204+
}
205+
}
206+
207+
return false;
160208
}
161209

162210
public class BusMutexLockingFailedException : EmbeddedController.IOException
@@ -195,49 +243,4 @@ private enum Status : byte
195243
SciEventPending = 0x20, // SCI_EVT
196244
SmiEventPending = 0x40 // SMI_EVT
197245
}
198-
199-
#region Read/Write ops
200-
201-
protected bool ReadByteOp(byte register, out byte value)
202-
{
203-
if (WaitWrite())
204-
{
205-
WriteIOPort(Port.Command, (byte)Command.Read);
206-
207-
if (WaitWrite())
208-
{
209-
WriteIOPort(Port.Data, register);
210-
211-
if (WaitWrite() && WaitRead())
212-
{
213-
value = ReadIOPort(Port.Data);
214-
return true;
215-
}
216-
}
217-
}
218-
219-
value = 0;
220-
return false;
221-
}
222-
223-
protected bool WriteByteOp(byte register, byte value)
224-
{
225-
if (WaitWrite())
226-
{
227-
WriteIOPort(Port.Command, (byte)Command.Write);
228-
if (WaitWrite())
229-
{
230-
WriteIOPort(Port.Data, register);
231-
if (WaitWrite())
232-
{
233-
WriteIOPort(Port.Data, value);
234-
return true;
235-
}
236-
}
237-
}
238-
239-
return false;
240-
}
241-
242-
#endregion
243246
}

OpenHardwareMonitorLib/Hardware/Motherboard/Model.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ public enum Model
103103
TUF_X470_PLUS_GAMING,
104104
TUF_GAMING_X870_PLUS_WIFI,
105105
Z170_A,
106+
Z170_PRO_GAMING,
106107
B150M_C,
107108
B150M_C_D3,
108109
TUF_GAMING_X570_PLUS_WIFI,

0 commit comments

Comments
 (0)