diff --git a/LibreHardwareMonitorLib/Hardware/Motherboard/Lpc/EC/EmbeddedController.cs b/LibreHardwareMonitorLib/Hardware/Motherboard/Lpc/EC/EmbeddedController.cs index 05d3af0..4545d09 100644 --- a/LibreHardwareMonitorLib/Hardware/Motherboard/Lpc/EC/EmbeddedController.cs +++ b/LibreHardwareMonitorLib/Hardware/Motherboard/Lpc/EC/EmbeddedController.cs @@ -12,25 +12,37 @@ namespace LibreHardwareMonitor.Hardware.Motherboard.Lpc.EC { public abstract class EmbeddedController : Hardware { - private readonly List _sensors; + private readonly IReadOnlyList _sources; + private readonly List _sensors; + private readonly ushort[] _registers; + private readonly byte[] _data; protected EmbeddedController(List sources, ISettings settings) : base("Embedded Controller", new Identifier("lpc", "ec"), settings) { + _sources = sources; var indices = new Dictionary(); foreach (SensorType t in Enum.GetValues(typeof(SensorType))) { indices.Add(t, 0); } - _sensors = new List(); - foreach (EmbeddedControllerSource s in sources) + _sensors = new List(); + List 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; } } } diff --git a/LibreHardwareMonitorLib/Hardware/Motherboard/Lpc/EC/EmbeddedControllerReader.cs b/LibreHardwareMonitorLib/Hardware/Motherboard/Lpc/EC/EmbeddedControllerReader.cs index c0a5668..344980c 100644 --- a/LibreHardwareMonitorLib/Hardware/Motherboard/Lpc/EC/EmbeddedControllerReader.cs +++ b/LibreHardwareMonitorLib/Hardware/Motherboard/Lpc/EC/EmbeddedControllerReader.cs @@ -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); } diff --git a/LibreHardwareMonitorLib/Hardware/Motherboard/Lpc/EC/EmbeddedControllerSource.cs b/LibreHardwareMonitorLib/Hardware/Motherboard/Lpc/EC/EmbeddedControllerSource.cs index 0ec9f23..a804184 100644 --- a/LibreHardwareMonitorLib/Hardware/Motherboard/Lpc/EC/EmbeddedControllerSource.cs +++ b/LibreHardwareMonitorLib/Hardware/Motherboard/Lpc/EC/EmbeddedControllerSource.cs @@ -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; } diff --git a/LibreHardwareMonitorLib/Hardware/Motherboard/Lpc/EC/IEmbeddedControllerIO.cs b/LibreHardwareMonitorLib/Hardware/Motherboard/Lpc/EC/IEmbeddedControllerIO.cs index c12fbf3..3149b6b 100644 --- a/LibreHardwareMonitorLib/Hardware/Motherboard/Lpc/EC/IEmbeddedControllerIO.cs +++ b/LibreHardwareMonitorLib/Hardware/Motherboard/Lpc/EC/IEmbeddedControllerIO.cs @@ -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); } } diff --git a/LibreHardwareMonitorLib/Hardware/Motherboard/Lpc/EC/WindowsEmbeddedControllerIO.cs b/LibreHardwareMonitorLib/Hardware/Motherboard/Lpc/EC/WindowsEmbeddedControllerIO.cs index 2d8a6de..e8d16de 100644 --- a/LibreHardwareMonitorLib/Hardware/Motherboard/Lpc/EC/WindowsEmbeddedControllerIO.cs +++ b/LibreHardwareMonitorLib/Hardware/Motherboard/Lpc/EC/WindowsEmbeddedControllerIO.cs @@ -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(register, ReadByteOp); } - public ushort ReadWordLE(byte register) - { - return ReadLoop(register, ReadWordLEOp); - } - - public ushort ReadWordBE(byte register) - { - return ReadLoop(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(byte register, ReadOp 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 } } diff --git a/LibreHardwareMonitorLib/Hardware/Motherboard/Lpc/Nct677X.cs b/LibreHardwareMonitorLib/Hardware/Motherboard/Lpc/Nct677X.cs index ee00b45..3dc22f8 100644 --- a/LibreHardwareMonitorLib/Hardware/Motherboard/Lpc/Nct677X.cs +++ b/LibreHardwareMonitorLib/Hardware/Motherboard/Lpc/Nct677X.cs @@ -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")] diff --git a/LibreHardwareMonitorLib/Hardware/Motherboard/SuperIOHardware.cs b/LibreHardwareMonitorLib/Hardware/Motherboard/SuperIOHardware.cs index fa98419..d8f0570 100644 --- a/LibreHardwareMonitorLib/Hardware/Motherboard/SuperIOHardware.cs +++ b/LibreHardwareMonitorLib/Hardware/Motherboard/SuperIOHardware.cs @@ -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; }