Fixes for ASUS Crosshair VIII Hero (#540)

This commit is contained in:
Eugene Shalygin
2021-09-19 10:22:55 +02:00
committed by GitHub
parent 05b271a85a
commit c0fe15050f
7 changed files with 109 additions and 142 deletions
@@ -12,25 +12,37 @@ namespace LibreHardwareMonitor.Hardware.Motherboard.Lpc.EC
{
public abstract class EmbeddedController : Hardware
{
private readonly List<EmbeddedControllerSensor> _sensors;
private readonly IReadOnlyList<EmbeddedControllerSource> _sources;
private readonly List<Sensor> _sensors;
private readonly ushort[] _registers;
private readonly byte[] _data;
protected EmbeddedController(List<EmbeddedControllerSource> sources, ISettings settings) : base("Embedded Controller", new Identifier("lpc", "ec"), settings)
{
_sources = sources;
var indices = new Dictionary<SensorType, int>();
foreach (SensorType t in Enum.GetValues(typeof(SensorType)))
{
indices.Add(t, 0);
}
_sensors = new List<EmbeddedControllerSensor>();
foreach (EmbeddedControllerSource s in sources)
_sensors = new List<Sensor>();
List<ushort> registers = new();
foreach (EmbeddedControllerSource s in sources)
{
int index = indices[s.Type];
indices[s.Type] = index + 1;
_sensors.Add(new EmbeddedControllerSensor(s, index, this, settings));
_sensors.Add(new Sensor(s.Name, index, s.Type, this, settings));
for (int i = 0; i < s.Size; ++i)
{
registers.Add((ushort)(s.Register + i));
}
ActivateSensor(_sensors[_sensors.Count - 1]);
}
_registers = registers.ToArray();
_data = new byte[_registers.Length];
}
public override HardwareType HardwareType => HardwareType.EmbeddedController;
@@ -47,13 +59,13 @@ namespace LibreHardwareMonitor.Hardware.Motherboard.Lpc.EC
{
sources.AddRange(new EmbeddedControllerSource[]
{
new("Chipset", 0x3A, SensorType.Temperature, ReadByte),
new("CPU", 0x3B, SensorType.Temperature, ReadByte),
new("Motherboard", 0x3C, SensorType.Temperature, ReadByte),
new("T Sensor", 0x3D, SensorType.Temperature, ReadByte),
new("VRM", 0x3E, SensorType.Temperature, ReadByte),
new("CPU Opt", 0xB0, SensorType.Fan, ReadWordBE),
new("CPU", 0xF4, SensorType.Current, ReadByte)
new("Chipset", SensorType.Temperature, 0x003A, 1),
new("CPU", SensorType.Temperature, 0x003B, 1),
new("Motherboard", SensorType.Temperature, 0x003C, 1),
new("T Sensor", SensorType.Temperature, 0x003D, 1, blank: 0xD8),
new("VRM", SensorType.Temperature, 0x003E, 1),
new("CPU Opt", SensorType.Fan, 0x00B0, 2),
new("CPU", SensorType.Current, 0x00F4, 1)
});
break;
@@ -65,7 +77,7 @@ namespace LibreHardwareMonitor.Hardware.Motherboard.Lpc.EC
case Model.ROG_STRIX_X570_E_GAMING:
case Model.ROG_CROSSHAIR_VIII_HERO:
{
sources.Add(new EmbeddedControllerSource("Chipset", 0xB4, SensorType.Fan, ReadWordBE));
sources.Add(new EmbeddedControllerSource("Chipset", SensorType.Fan, 0x00B4, 2));
break;
}
}
@@ -76,7 +88,9 @@ namespace LibreHardwareMonitor.Hardware.Motherboard.Lpc.EC
case Model.ROG_CROSSHAIR_VIII_DARK_HERO:
{
// TODO: "why 42?" is a silly question, I know, but still, why? On the serious side, it might be 41.6(6)
sources.Add(new EmbeddedControllerSource("Flow Rate", 0xBC, SensorType.Flow, (ecIO, port) => ecIO.ReadWordBE(port) / 42f * 60f));
sources.Add(new EmbeddedControllerSource("Flow Rate", SensorType.Flow, 0x00BC, 2, 1.0f / 42f * 60f));
sources.Add(new EmbeddedControllerSource("Water In", SensorType.Temperature, 0x0100, 1, blank: 0xD8));
sources.Add(new EmbeddedControllerSource("Water Out", SensorType.Temperature, 0x0101, 1, blank: 0xD8));
break;
}
}
@@ -95,18 +109,22 @@ namespace LibreHardwareMonitor.Hardware.Motherboard.Lpc.EC
public override void Update()
{
try
{
using IEmbeddedControllerIO embeddedControllerIO = AcquireIOInterface();
foreach (EmbeddedControllerSensor sensor in _sensors)
{
sensor.Update(embeddedControllerIO);
}
}
catch (WindowsEmbeddedControllerIO.BusMutexLockingFailedException)
if (!TryUpdateData())
{
// just skip this update cycle?
return;
}
int readRegister = 0;
for (int si = 0; si < _sensors.Count; ++si)
{
int val = 0;
for (int i = 0; i < _sources[si].Size; ++i, ++readRegister)
{
val = (val << 8) + _data[readRegister];
}
_sensors[si].Value = val != _sources[si].Blank ? val * _sources[si].Factor : null;
}
}
@@ -123,7 +141,13 @@ namespace LibreHardwareMonitor.Hardware.Motherboard.Lpc.EC
try
{
using IEmbeddedControllerIO embeddedControllerIO = AcquireIOInterface();
ushort[] src = new ushort[0x100];
byte[] data = new byte[0x100];
for (ushort i = 0; i < src.Length; ++i)
{
src[i] = i;
}
embeddedControllerIO.Read(src, data);
for (int i = 0; i <= 0xF; ++i)
{
r.Append(" ");
@@ -133,7 +157,7 @@ namespace LibreHardwareMonitor.Hardware.Motherboard.Lpc.EC
{
byte address = (byte)(i << 4 | j);
r.Append(" ");
r.Append(embeddedControllerIO.ReadByte(address).ToString("X2", CultureInfo.InvariantCulture));
r.Append(data[address].ToString("X2", CultureInfo.InvariantCulture));
}
r.AppendLine();
@@ -147,38 +171,19 @@ namespace LibreHardwareMonitor.Hardware.Motherboard.Lpc.EC
return r.ToString();
}
public static float ReadByte(IEmbeddedControllerIO ecIO, byte port)
{
return ecIO.ReadByte(port);
}
public static float ReadWordLE(IEmbeddedControllerIO ecIO, byte port)
{
return ecIO.ReadWordLE(port);
}
public static float ReadWordBE(IEmbeddedControllerIO ecIO, byte port)
{
return ecIO.ReadWordBE(port);
}
protected abstract IEmbeddedControllerIO AcquireIOInterface();
private class EmbeddedControllerSensor : Sensor
private bool TryUpdateData()
{
readonly byte _port;
readonly EmbeddedControllerReader _reader;
public EmbeddedControllerSensor(EmbeddedControllerSource embeddedControllerSource, int index, EmbeddedController hardware, ISettings settings)
: base(embeddedControllerSource.Name, index, embeddedControllerSource.Type, hardware, settings)
try
{
_port = embeddedControllerSource.Port;
_reader = embeddedControllerSource.Reader;
using IEmbeddedControllerIO embeddedControllerIO = AcquireIOInterface();
embeddedControllerIO.Read(_registers, _data);
return true;
}
public void Update(IEmbeddedControllerIO ecIO)
catch (WindowsEmbeddedControllerIO.BusMutexLockingFailedException)
{
Value = _reader(ecIO, _port);
return false;
}
}
}
@@ -5,5 +5,5 @@
namespace LibreHardwareMonitor.Hardware.Motherboard.Lpc.EC
{
public delegate float EmbeddedControllerReader(IEmbeddedControllerIO ecIO, byte port);
public delegate float EmbeddedControllerReader(IEmbeddedControllerIO ecIO, ushort register);
}
@@ -7,17 +7,23 @@ namespace LibreHardwareMonitor.Hardware.Motherboard.Lpc.EC
{
public class EmbeddedControllerSource
{
public EmbeddedControllerSource(string name, byte port, SensorType type, EmbeddedControllerReader reader)
public EmbeddedControllerSource(string name, SensorType type, ushort register, byte size, float factor = 1.0f, uint blank = uint.MaxValue)
{
Name = name;
Port = port;
Register = register;
Size = size;
Type = type;
Reader = reader;
Factor = factor;
Blank = blank;
}
public string Name { get; }
public ushort Register { get; }
public byte Size { get; }
public float Factor { get; }
public byte Port { get; }
public uint Blank { get; }
public EmbeddedControllerReader Reader { get; }
@@ -9,14 +9,6 @@ namespace LibreHardwareMonitor.Hardware.Motherboard.Lpc.EC
{
public interface IEmbeddedControllerIO : IDisposable
{
void WriteByte(byte register, byte value);
void WriteWord(byte register, ushort value);
byte ReadByte(byte register);
ushort ReadWordBE(byte register);
ushort ReadWordLE(byte register);
void Read(ushort[] registers, byte[] data);
}
}
@@ -4,6 +4,7 @@
// All Rights Reserved.
using System;
using System.Diagnostics;
using System.Threading;
namespace LibreHardwareMonitor.Hardware.Motherboard.Lpc.EC
@@ -35,30 +36,32 @@ namespace LibreHardwareMonitor.Hardware.Motherboard.Lpc.EC
}
}
public byte ReadByte(byte register)
public void Read(ushort[] registers, byte[] data)
{
Trace.Assert(registers.Length <= data.Length,
"data buffer length has to be greater or equal to the registers array length");
for (int i = 0; i < registers.Length; ++i)
{
byte bank = (byte)(registers[i] >> 8);
byte index = (byte)(registers[i] & 0xFF);
SwitchBank(bank);
data[i] = ReadByte(index);
}
SwitchBank(0);
}
private byte ReadByte(byte register)
{
return ReadLoop<byte>(register, ReadByteOp);
}
public ushort ReadWordLE(byte register)
{
return ReadLoop<ushort>(register, ReadWordLEOp);
}
public ushort ReadWordBE(byte register)
{
return ReadLoop<ushort>(register, ReadWordBEOp);
}
public void WriteByte(byte register, byte value)
private void WriteByte(byte register, byte value)
{
WriteLoop(register, value, WriteByteOp);
}
public void WriteWord(byte register, ushort value)
{
WriteLoop(register, value, WriteWordOp);
}
public void Dispose()
{
@@ -69,6 +72,13 @@ namespace LibreHardwareMonitor.Hardware.Motherboard.Lpc.EC
}
}
private byte SwitchBank(byte bank)
{
byte previous = ReadByte(0xFF);
WriteByte(0xFF, bank);
return previous;
}
private TResult ReadLoop<TResult>(byte register, ReadOp<TResult> op) where TResult : new()
{
TResult result = new();
@@ -182,7 +192,7 @@ namespace LibreHardwareMonitor.Hardware.Motherboard.Lpc.EC
}
#region Read/Write ops
#region Read/Write ops
protected bool ReadByteOp(byte register, out byte value)
{
@@ -225,47 +235,6 @@ namespace LibreHardwareMonitor.Hardware.Motherboard.Lpc.EC
return false;
}
protected bool ReadWordLEOp(byte register, out ushort value)
{
return ReadWordOp(register, (byte)(register + 1), out value);
}
protected bool ReadWordBEOp(byte register, out ushort value)
{
return ReadWordOp((byte)(register + 1), register, out value);
}
protected bool ReadWordOp(byte registerLsb, byte registerMsb, out ushort value)
{
value = 0;
if (!ReadByteOp(registerLsb, out byte result))
{
return false;
}
value = result;
if (!ReadByteOp(registerMsb, out result))
{
return false;
}
value |= (ushort)(result << 8);
return true;
}
protected bool WriteWordOp(byte register, ushort value)
{
//Byte order: little endia
byte msb = (byte)(value >> 8);
byte lsb = (byte)value;
return WriteByteOp(register, lsb) && WriteByteOp((byte)(register + 1), msb);
}
#endregion
#endregion
}
}
@@ -224,15 +224,6 @@ namespace LibreHardwareMonitor.Hardware.Motherboard.Lpc
new TemperatureSourceData(SourceNct67Xxd.PECI_1_CAL, 0),
new TemperatureSourceData(SourceNct67Xxd.VIRTUAL_TEMP, 0)
});
if (chip == Chip.NCT6798D)
{
temperaturesSources.AddRange(new TemperatureSourceData[]
{
new TemperatureSourceData(SourceNct67Xxd.WATER_IN, 0xC33),
new TemperatureSourceData(SourceNct67Xxd.WATER_OUT, 0xC39)
});
}
break;
}
default:
@@ -990,9 +981,7 @@ namespace LibreHardwareMonitor.Hardware.Motherboard.Lpc
BYTE_TEMP1 = 27,
PECI_0_CAL = 28,
PECI_1_CAL = 29,
VIRTUAL_TEMP = 31,
WATER_IN = 32,
WATER_OUT = 33
VIRTUAL_TEMP = 31
}
[SuppressMessage("ReSharper", "InconsistentNaming")]
@@ -2405,14 +2405,20 @@ namespace LibreHardwareMonitor.Hardware.Motherboard
t.Add(new Temperature("PECI 0 Calibrated", 21));
t.Add(new Temperature("PECI 1 Calibrated", 22));
t.Add(new Temperature("Virtual", 23));
t.Add(new Temperature("Water In", 24));
t.Add(new Temperature("Water Out", 25));
for (int i = 0; i < superIO.Fans.Length; i++)
f.Add(new Fan("Fan #" + (i + 1), i));
string[] fanControlNames = {"Chassis Fan 1", "CPU Fan", "Chassis Fan 2",
"Chassis Fan 3", "High Amp Fan", "W_PUMP+", "AIO Pump"};
System.Diagnostics.Debug.Assert(fanControlNames.Length == superIO.Fans.Length,
string.Format("Expected {0} fan register in the SuperIO chip", fanControlNames.Length));
System.Diagnostics.Debug.Assert(superIO.Fans.Length == superIO.Controls.Length,
"Expected counts of fan controls and fan speed registers to be equal");
for (int i = 0; i < fanControlNames.Length; i++)
f.Add(new Fan(fanControlNames[i], i));
for (int i = 0; i < fanControlNames.Length; i++)
c.Add(new Ctrl(fanControlNames[i], i));
for (int i = 0; i < superIO.Controls.Length; i++)
c.Add(new Ctrl("Fan Control #" + (i + 1), i));
break;
}