diff --git a/LibreHardwareMonitor/UI/HardwareTypeImage.cs b/LibreHardwareMonitor/UI/HardwareTypeImage.cs index 979a4e0..e30aebb 100644 --- a/LibreHardwareMonitor/UI/HardwareTypeImage.cs +++ b/LibreHardwareMonitor/UI/HardwareTypeImage.cs @@ -42,6 +42,7 @@ namespace LibreHardwareMonitor.UI image = Utilities.EmbeddedResources.GetImage("mainboard.png"); break; case HardwareType.SuperIO: + case HardwareType.EmbeddedController: image = Utilities.EmbeddedResources.GetImage("chip.png"); break; case HardwareType.Memory: diff --git a/LibreHardwareMonitor/UI/PlotPanel.cs b/LibreHardwareMonitor/UI/PlotPanel.cs index 12426fb..60781c1 100644 --- a/LibreHardwareMonitor/UI/PlotPanel.cs +++ b/LibreHardwareMonitor/UI/PlotPanel.cs @@ -160,6 +160,7 @@ namespace LibreHardwareMonitor.UI var units = new Dictionary { { SensorType.Voltage, "V" }, + { SensorType.Current, "A" }, { SensorType.Clock, "MHz" }, { SensorType.Temperature, "°C" }, { SensorType.Load, "%" }, diff --git a/LibreHardwareMonitor/UI/SensorGadget.cs b/LibreHardwareMonitor/UI/SensorGadget.cs index 540c793..dae5ad6 100644 --- a/LibreHardwareMonitor/UI/SensorGadget.cs +++ b/LibreHardwareMonitor/UI/SensorGadget.cs @@ -610,6 +610,9 @@ namespace LibreHardwareMonitor.UI case SensorType.Voltage: format = "{0:F3} V"; break; + case SensorType.Current: + format = "{0:F3} A"; + break; case SensorType.Clock: format = "{0:F0} MHz"; break; diff --git a/LibreHardwareMonitor/UI/SensorNode.cs b/LibreHardwareMonitor/UI/SensorNode.cs index 0c0f6c5..bd0be34 100644 --- a/LibreHardwareMonitor/UI/SensorNode.cs +++ b/LibreHardwareMonitor/UI/SensorNode.cs @@ -94,6 +94,7 @@ namespace LibreHardwareMonitor.UI switch (sensor.SensorType) { case SensorType.Voltage: Format = "{0:F3} V"; break; + case SensorType.Current: Format = "{0:F3} A"; break; case SensorType.Clock: Format = "{0:F1} MHz"; break; case SensorType.Load: Format = "{0:F1} %"; break; case SensorType.Temperature: Format = "{0:F1} °C"; break; diff --git a/LibreHardwareMonitor/UI/SensorNotifyIcon.cs b/LibreHardwareMonitor/UI/SensorNotifyIcon.cs index c58c203..1ab1e7b 100644 --- a/LibreHardwareMonitor/UI/SensorNotifyIcon.cs +++ b/LibreHardwareMonitor/UI/SensorNotifyIcon.cs @@ -163,6 +163,8 @@ namespace LibreHardwareMonitor.UI { case SensorType.Voltage: return $"{Sensor.Value:F1}"; + case SensorType.Current: + return $"{Sensor.Value:F1}"; case SensorType.Clock: return $"{1e-3f * Sensor.Value:F1}"; case SensorType.Load: @@ -244,6 +246,7 @@ namespace LibreHardwareMonitor.UI switch (Sensor.SensorType) { case SensorType.Voltage: format = "\n{0}: {1:F2} V"; break; + case SensorType.Current: format = "\n{0}: {1:F2} A"; break; case SensorType.Clock: format = "\n{0}: {1:F0} MHz"; break; case SensorType.Load: format = "\n{0}: {1:F1} %"; break; case SensorType.Temperature: format = "\n{0}: {1:F1} °C"; break; diff --git a/LibreHardwareMonitor/UI/TypeNode.cs b/LibreHardwareMonitor/UI/TypeNode.cs index b23f080..18a6610 100644 --- a/LibreHardwareMonitor/UI/TypeNode.cs +++ b/LibreHardwareMonitor/UI/TypeNode.cs @@ -27,6 +27,10 @@ namespace LibreHardwareMonitor.UI Image = Utilities.EmbeddedResources.GetImage("voltage.png"); Text = "Voltages"; break; + case SensorType.Current: + Image = Utilities.EmbeddedResources.GetImage("voltage.png"); + Text = "Currents"; + break; case SensorType.Clock: Image = Utilities.EmbeddedResources.GetImage("clock.png"); Text = "Clocks"; diff --git a/LibreHardwareMonitor/Utilities/HttpServer.cs b/LibreHardwareMonitor/Utilities/HttpServer.cs index 69a8184..7a43375 100644 --- a/LibreHardwareMonitor/Utilities/HttpServer.cs +++ b/LibreHardwareMonitor/Utilities/HttpServer.cs @@ -651,6 +651,7 @@ namespace LibreHardwareMonitor.Utilities switch (tn.SensorType) { case SensorType.Voltage: + case SensorType.Current: return "voltage.png"; case SensorType.Clock: return "clock.png"; diff --git a/LibreHardwareMonitorLib/Hardware/IHardware.cs b/LibreHardwareMonitorLib/Hardware/IHardware.cs index 49d1af5..6faf48e 100644 --- a/LibreHardwareMonitorLib/Hardware/IHardware.cs +++ b/LibreHardwareMonitorLib/Hardware/IHardware.cs @@ -18,7 +18,8 @@ namespace LibreHardwareMonitor.Hardware GpuAmd, Storage, Network, - Cooler + Cooler, + EmbeddedController } public interface IHardware : IElement diff --git a/LibreHardwareMonitorLib/Hardware/ISensor.cs b/LibreHardwareMonitorLib/Hardware/ISensor.cs index c45dd31..2fe2b32 100644 --- a/LibreHardwareMonitorLib/Hardware/ISensor.cs +++ b/LibreHardwareMonitorLib/Hardware/ISensor.cs @@ -12,6 +12,7 @@ namespace LibreHardwareMonitor.Hardware public enum SensorType { Voltage, // V + Current, // A Clock, // MHz Temperature, // °C Load, // % diff --git a/LibreHardwareMonitorLib/Hardware/Motherboard/Identification.cs b/LibreHardwareMonitorLib/Hardware/Motherboard/Identification.cs index 3dda966..22ae879 100644 --- a/LibreHardwareMonitorLib/Hardware/Motherboard/Identification.cs +++ b/LibreHardwareMonitorLib/Hardware/Motherboard/Identification.cs @@ -141,6 +141,8 @@ namespace LibreHardwareMonitor.Hardware.Motherboard return Model.P55_Deluxe; case var _ when name.Equals("Crosshair III Formula", StringComparison.OrdinalIgnoreCase): return Model.CROSSHAIR_III_FORMULA; + case var _ when name.Equals("ROG CROSSHAIR VIII HERO", StringComparison.OrdinalIgnoreCase): + return Model.ROG_CROSSHAIR_VIII_HERO; case var _ when name.Equals("M2N-SLI DELUXE", StringComparison.OrdinalIgnoreCase): return Model.M2N_SLI_Deluxe; case var _ when name.Equals("M4A79XTD EVO", StringComparison.OrdinalIgnoreCase): diff --git a/LibreHardwareMonitorLib/Hardware/Motherboard/Lpc/EC/EmbeddedController.cs b/LibreHardwareMonitorLib/Hardware/Motherboard/Lpc/EC/EmbeddedController.cs new file mode 100644 index 0000000..755dfa2 --- /dev/null +++ b/LibreHardwareMonitorLib/Hardware/Motherboard/Lpc/EC/EmbeddedController.cs @@ -0,0 +1,136 @@ +// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. +// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. +// Copyright (C) LibreHardwareMonitor and Contributors. +// All Rights Reserved. + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Text; + +namespace LibreHardwareMonitor.Hardware.Motherboard.Lpc.EC +{ + public abstract class EmbeddedController : Hardware + { + private readonly List _sensors; + + protected EmbeddedController(List sources, ISettings settings) : base("Embedded Controller", new Identifier("lpc", "ec"), settings) + { + var indices = new Dictionary(); + foreach (SensorType t in Enum.GetValues(typeof(SensorType))) + { + indices.Add(t, 0); + } + + _sensors = new List(); + foreach (EmbeddedControllerSource s in sources) + { + int index = indices[s.Type]; + indices[s.Type] = index + 1; + _sensors.Add(new EmbeddedControllerSensor(s, index, this, settings)); + + ActivateSensor(_sensors[_sensors.Count - 1]); + } + } + + public override HardwareType HardwareType => HardwareType.EmbeddedController; + + public static EmbeddedController Create(List sources, ISettings settings) + { + return Environment.OSVersion.Platform switch + { + PlatformID.Win32NT => new WindowsEmbeddedController(sources, settings), + _ => null + }; + } + + public override void Update() + { + try + { + using IEmbeddedControllerIO embeddedControllerIO = AcquireIOInterface(); + + foreach (EmbeddedControllerSensor sensor in _sensors) + { + sensor.Update(embeddedControllerIO); + } + } + catch (WindowsEmbeddedControllerIO.BusMutexLockingFailedException) + { + // just skip this update cycle? + } + } + + public override string GetReport() + { + StringBuilder r = new(); + + r.AppendLine("EC " + GetType().Name); + r.AppendLine("Embedded Controller Registers"); + r.AppendLine(); + r.AppendLine(" 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F"); + r.AppendLine(); + + try + { + using IEmbeddedControllerIO embeddedControllerIO = AcquireIOInterface(); + + for (int i = 0; i <= 0xF; ++i) + { + r.Append(" "); + r.Append((i << 4).ToString("X2", CultureInfo.InvariantCulture)); + r.Append(" "); + for (int j = 0; j <= 0xF; ++j) + { + byte address = (byte)(i << 4 | j); + r.Append(" "); + r.Append(embeddedControllerIO.ReadByte(address).ToString("X2", CultureInfo.InvariantCulture)); + } + + r.AppendLine(); + } + } + catch (WindowsEmbeddedControllerIO.BusMutexLockingFailedException e) + { + r.AppendLine(e.Message); + } + + 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 + { + readonly byte _port; + readonly EmbeddedControllerReader _reader; + + public EmbeddedControllerSensor(EmbeddedControllerSource embeddedControllerSource, int index, EmbeddedController hardware, ISettings settings) + : base(embeddedControllerSource.Name, index, embeddedControllerSource.Type, hardware, settings) + { + _port = embeddedControllerSource.Port; + _reader = embeddedControllerSource.Reader; + } + + public void Update(IEmbeddedControllerIO ecIO) + { + Value = _reader(ecIO, _port); + } + } + } +} diff --git a/LibreHardwareMonitorLib/Hardware/Motherboard/Lpc/EC/EmbeddedControllerReader.cs b/LibreHardwareMonitorLib/Hardware/Motherboard/Lpc/EC/EmbeddedControllerReader.cs new file mode 100644 index 0000000..c0a5668 --- /dev/null +++ b/LibreHardwareMonitorLib/Hardware/Motherboard/Lpc/EC/EmbeddedControllerReader.cs @@ -0,0 +1,9 @@ +// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. +// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. +// Copyright (C) LibreHardwareMonitor and Contributors. +// All Rights Reserved. + +namespace LibreHardwareMonitor.Hardware.Motherboard.Lpc.EC +{ + public delegate float EmbeddedControllerReader(IEmbeddedControllerIO ecIO, byte port); +} diff --git a/LibreHardwareMonitorLib/Hardware/Motherboard/Lpc/EC/EmbeddedControllerSource.cs b/LibreHardwareMonitorLib/Hardware/Motherboard/Lpc/EC/EmbeddedControllerSource.cs new file mode 100644 index 0000000..0ec9f23 --- /dev/null +++ b/LibreHardwareMonitorLib/Hardware/Motherboard/Lpc/EC/EmbeddedControllerSource.cs @@ -0,0 +1,26 @@ +// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. +// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. +// Copyright (C) LibreHardwareMonitor and Contributors. +// All Rights Reserved. + +namespace LibreHardwareMonitor.Hardware.Motherboard.Lpc.EC +{ + public class EmbeddedControllerSource + { + public EmbeddedControllerSource(string name, byte port, SensorType type, EmbeddedControllerReader reader) + { + Name = name; + Port = port; + Type = type; + Reader = reader; + } + + public string Name { get; } + + public byte Port { get; } + + public EmbeddedControllerReader Reader { get; } + + public SensorType Type { get; } + } +} diff --git a/LibreHardwareMonitorLib/Hardware/Motherboard/Lpc/EC/IEmbeddedControllerIO.cs b/LibreHardwareMonitorLib/Hardware/Motherboard/Lpc/EC/IEmbeddedControllerIO.cs new file mode 100644 index 0000000..c12fbf3 --- /dev/null +++ b/LibreHardwareMonitorLib/Hardware/Motherboard/Lpc/EC/IEmbeddedControllerIO.cs @@ -0,0 +1,22 @@ +// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. +// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. +// Copyright (C) LibreHardwareMonitor and Contributors. +// All Rights Reserved. + +using System; + +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); + } +} diff --git a/LibreHardwareMonitorLib/Hardware/Motherboard/Lpc/EC/WindowsEmbeddedController.cs b/LibreHardwareMonitorLib/Hardware/Motherboard/Lpc/EC/WindowsEmbeddedController.cs new file mode 100644 index 0000000..ec0e66b --- /dev/null +++ b/LibreHardwareMonitorLib/Hardware/Motherboard/Lpc/EC/WindowsEmbeddedController.cs @@ -0,0 +1,20 @@ +// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. +// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. +// Copyright (C) LibreHardwareMonitor and Contributors. +// All Rights Reserved. + +using System.Collections.Generic; + +namespace LibreHardwareMonitor.Hardware.Motherboard.Lpc.EC +{ + public class WindowsEmbeddedController : EmbeddedController + { + public WindowsEmbeddedController(List sources, ISettings settings) : base(sources, settings) + { } + + protected override IEmbeddedControllerIO AcquireIOInterface() + { + return new WindowsEmbeddedControllerIO(); + } + } +} diff --git a/LibreHardwareMonitorLib/Hardware/Motherboard/Lpc/EC/WindowsEmbeddedControllerIO.cs b/LibreHardwareMonitorLib/Hardware/Motherboard/Lpc/EC/WindowsEmbeddedControllerIO.cs new file mode 100644 index 0000000..3f151b6 --- /dev/null +++ b/LibreHardwareMonitorLib/Hardware/Motherboard/Lpc/EC/WindowsEmbeddedControllerIO.cs @@ -0,0 +1,284 @@ +// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. +// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. +// Copyright (C) LibreHardwareMonitor and Contributors. +// All Rights Reserved. + +using System; +using System.Threading; + +namespace LibreHardwareMonitor.Hardware.Motherboard.Lpc.EC +{ + /// + /// An unsafe but universal implementation for the ACPI Embedded Controller IO interface for Windows + /// + /// + /// It is unsafe because of possible race condition between this application and the PC firmware when + /// writing to the EC registers. For a safe approach ACPI/WMI methods have to be used, but those are + /// different for each motherboard model. + /// + public class WindowsEmbeddedControllerIO : IEmbeddedControllerIO + { + private const int FailuresBeforeSkip = 20; + private const int MaxRetries = 5; + + // implementation + private const int WaitSpins = 50; + private bool _disposedValue; + + private int _waitReadFailures; + + public WindowsEmbeddedControllerIO() + { + if (!Ring0.WaitIsaBusMutex(10)) + { + throw new BusMutexLockingFailedException(); + } + + _disposedValue = false; + } + + ~WindowsEmbeddedControllerIO() + { + Dispose(false); + } + + public 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) + { + WriteLoop(register, value, WriteByteOp); + } + + public void WriteWord(byte register, ushort value) + { + WriteLoop(register, value, WriteWordOp); + } + + protected virtual void Dispose(bool disposing) + { + if (!_disposedValue) + { + Ring0.ReleaseIsaBusMutex(); + _disposedValue = true; + } + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + private TResult ReadLoop(byte register, ReadOp op) where TResult : new() + { + TResult result = new(); + + for (int i = 0; i < MaxRetries; i++) + { + if (op(register, out result)) + { + return result; + } + } + + return result; + } + + private void WriteLoop(byte register, TValue value, WriteOp op) + { + for (int i = 0; i < MaxRetries; i++) + { + if (op(register, value)) + { + return; + } + } + } + + private bool WaitForStatus(Status status, bool isSet) + { + for (int i = 0; i < WaitSpins; i++) + { + byte value = ReadIOPort(Port.Command); + + if (((byte)status & (!isSet ? value : (byte)~value)) == 0) + { + return true; + } + + Thread.Sleep(1); + } + + return false; + } + + private bool WaitRead() + { + if (_waitReadFailures > FailuresBeforeSkip) + { + return true; + } + + if (WaitForStatus(Status.OutputBufferFull, true)) + { + _waitReadFailures = 0; + return true; + } + + _waitReadFailures++; + return false; + } + + private bool WaitWrite() + { + return WaitForStatus(Status.InputBufferFull, false); + } + + private byte ReadIOPort(Port port) + { + return Ring0.ReadIoPort((uint)port); + } + + private void WriteIOPort(Port port, byte datum) + { + Ring0.WriteIoPort((uint)port, datum); + } + + public class BusMutexLockingFailedException : ApplicationException + { + public BusMutexLockingFailedException() + : base("Could not lock ISA bus mutex") + { } + } + + private delegate bool ReadOp(byte register, out TParam p); + + private delegate bool WriteOp(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()) + { + WriteIOPort(Port.Command, (byte)Command.Read); + + if (WaitWrite()) + { + WriteIOPort(Port.Data, register); + + if (WaitWrite() && WaitRead()) + { + value = ReadIOPort(Port.Data); + return true; + } + } + } + + value = 0; + return false; + } + + protected bool WriteByteOp(byte register, byte value) + { + if (WaitWrite()) + { + WriteIOPort(Port.Command, (byte)Command.Write); + if (WaitWrite()) + { + WriteIOPort(Port.Data, register); + if (WaitWrite()) + { + WriteIOPort(Port.Data, value); + return true; + } + } + } + + 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 + } +} diff --git a/LibreHardwareMonitorLib/Hardware/Motherboard/Lpc/Nct677X.cs b/LibreHardwareMonitorLib/Hardware/Motherboard/Lpc/Nct677X.cs index 39dbaa8..2997dcf 100644 --- a/LibreHardwareMonitorLib/Hardware/Motherboard/Lpc/Nct677X.cs +++ b/LibreHardwareMonitorLib/Hardware/Motherboard/Lpc/Nct677X.cs @@ -5,6 +5,7 @@ // All Rights Reserved. using System; +using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Text; @@ -14,7 +15,25 @@ namespace LibreHardwareMonitor.Hardware.Motherboard.Lpc { internal class Nct677X : ISuperIO { - private readonly ushort?[] _alternateTemperatureRegister; + private readonly struct TemperatureSourceData + { + public TemperatureSourceData(Enum? source, ushort register, ushort halfRegister = 0, int halfBit = -1, ushort sourceRegister = 0, ushort? alternateRegister = null) + { + Source = source; + Register = register; + HalfRegister = halfRegister; + HalfBit = halfBit; + SourceRegister = sourceRegister; + AlternateRegister = alternateRegister; + } + public readonly Enum? Source; + public readonly ushort Register; + public readonly ushort HalfRegister; + public readonly int HalfBit; + public readonly ushort SourceRegister; + public readonly ushort? AlternateRegister; + }; + private readonly ushort[] _fanCountRegister; private readonly ushort[] _fanRpmRegister; private readonly byte[] _initialFanControlMode = new byte[7]; @@ -27,11 +46,7 @@ namespace LibreHardwareMonitor.Hardware.Motherboard.Lpc private readonly ushort _port; private readonly bool[] _restoreDefaultFanControlRequired = new bool[7]; private readonly byte _revision; - private readonly int[] _temperatureHalfBit; - private readonly ushort[] _temperatureHalfRegister; - private readonly ushort[] _temperatureRegister; - private readonly ushort[] _temperatureSourceRegister; - private readonly Enum[] _temperaturesSource; + private readonly TemperatureSourceData[] _temperaturesSource; private readonly ushort _vBatMonitorControlRegister; private readonly ushort[] _voltageRegisters; private readonly ushort _voltageVBatRegister; @@ -94,8 +109,6 @@ namespace LibreHardwareMonitor.Hardware.Motherboard.Lpc // min value RPM value with 16-bit fan counter _minFanRpm = (int)(1.35e6 / 0xFFFF); - - _temperaturesSource = new Enum[] { SourceNct6771F.PECI_0, SourceNct6771F.CPUTIN, SourceNct6771F.AUXTIN, SourceNct6771F.SYSTIN }; } else { @@ -103,8 +116,6 @@ namespace LibreHardwareMonitor.Hardware.Motherboard.Lpc // min value RPM value with 13-bit fan counter _minFanRpm = (int)(1.35e6 / 0x1FFF); - - _temperaturesSource = new Enum[] { SourceNct6776F.PECI_0, SourceNct6776F.CPUTIN, SourceNct6776F.AUXTIN, SourceNct6776F.SYSTIN }; } _fanRpmRegister = new ushort[5]; @@ -116,14 +127,20 @@ namespace LibreHardwareMonitor.Hardware.Motherboard.Lpc Voltages = new float?[9]; _voltageRegisters = new ushort[] { 0x020, 0x021, 0x022, 0x023, 0x024, 0x025, 0x026, 0x550, 0x551 }; _voltageVBatRegister = 0x551; + _temperaturesSource = new TemperatureSourceData[] + { + new TemperatureSourceData(chip == Chip.NCT6771F ? SourceNct6771F.PECI_0 : SourceNct6776F.PECI_0, 0x027, 0, -1, 0x621), + new TemperatureSourceData(chip == Chip.NCT6771F ? SourceNct6771F.CPUTIN : SourceNct6776F.CPUTIN, 0x073, 0x074, 7, 0x100), + new TemperatureSourceData(chip == Chip.NCT6771F ? SourceNct6771F.AUXTIN : SourceNct6776F.AUXTIN, 0x075, 0x076, 7, 0x200), + new TemperatureSourceData(chip == Chip.NCT6771F ? SourceNct6771F.SYSTIN : SourceNct6776F.SYSTIN, 0x077, 0x078, 7, 0x300), + new TemperatureSourceData(null, 0x150, 0x151, 7, 0x622), + new TemperatureSourceData(null, 0x250, 0x251, 7, 0x623), + new TemperatureSourceData(null, 0x62B, 0x62E, 0, 0x624), + new TemperatureSourceData(null, 0x62C, 0x62E, 1, 0x625), + new TemperatureSourceData(null, 0x62D, 0x62E, 2, 0x626) + }; Temperatures = new float?[4]; - _temperatureRegister = new ushort[] { 0x027, 0x073, 0x075, 0x077, 0x150, 0x250, 0x62B, 0x62C, 0x62D }; - _temperatureHalfRegister = new ushort[] { 0, 0x074, 0x076, 0x078, 0x151, 0x251, 0x62E, 0x62E, 0x62E }; - _temperatureHalfBit = new[] { -1, 7, 7, 7, 7, 7, 0, 1, 2 }; - _temperatureSourceRegister = new ushort[] { 0x621, 0x100, 0x200, 0x300, 0x622, 0x623, 0x624, 0x625, 0x626 }; - _alternateTemperatureRegister = new ushort?[] { null, null, null, null }; - break; } case Chip.NCT6779D: @@ -172,6 +189,7 @@ namespace LibreHardwareMonitor.Hardware.Motherboard.Lpc Voltages = new float?[15]; _voltageRegisters = new ushort[] { 0x480, 0x481, 0x482, 0x483, 0x484, 0x485, 0x486, 0x487, 0x488, 0x489, 0x48A, 0x48B, 0x48C, 0x48D, 0x48E }; _voltageVBatRegister = 0x488; + var temperaturesSources = new List(); switch (chip) { case Chip.NCT6796D: @@ -179,79 +197,61 @@ namespace LibreHardwareMonitor.Hardware.Motherboard.Lpc case Chip.NCT6797D: case Chip.NCT6798D: { - Temperatures = new float?[24]; - _temperaturesSource = new Enum[] + temperaturesSources.AddRange(new TemperatureSourceData[] { - SourceNct67Xxd.PECI_0, - SourceNct67Xxd.CPUTIN, - SourceNct67Xxd.SYSTIN, - SourceNct67Xxd.AUXTIN0, - SourceNct67Xxd.AUXTIN1, - SourceNct67Xxd.AUXTIN2, - SourceNct67Xxd.AUXTIN3, - SourceNct67Xxd.AUXTIN4, - SourceNct67Xxd.SMBUSMASTER0, - SourceNct67Xxd.SMBUSMASTER1, - SourceNct67Xxd.PECI_1, - SourceNct67Xxd.PCH_CHIP_CPU_MAX_TEMP, - SourceNct67Xxd.PCH_CHIP_TEMP, - SourceNct67Xxd.PCH_CPU_TEMP, - SourceNct67Xxd.PCH_MCH_TEMP, - SourceNct67Xxd.AGENT0_DIMM0, - SourceNct67Xxd.AGENT0_DIMM1, - SourceNct67Xxd.AGENT1_DIMM0, - SourceNct67Xxd.AGENT1_DIMM1, - SourceNct67Xxd.BYTE_TEMP0, - SourceNct67Xxd.BYTE_TEMP1, - SourceNct67Xxd.PECI_0_CAL, - SourceNct67Xxd.PECI_1_CAL, - SourceNct67Xxd.VIRTUAL_TEMP - }; + new TemperatureSourceData(SourceNct67Xxd.PECI_0, 0x073, 0x074, 7, 0x100), + new TemperatureSourceData(SourceNct67Xxd.CPUTIN, 0x075, 0x076, 7, 0x200, 0x491), + new TemperatureSourceData(SourceNct67Xxd.SYSTIN, 0x077, 0x078, 7, 0x300, 0x490), + new TemperatureSourceData(SourceNct67Xxd.AUXTIN0, 0x079, 0x07A, 7, 0x800, 0x492), + new TemperatureSourceData(SourceNct67Xxd.AUXTIN1, 0x07B, 0x07C, 7, 0x900, 0x493), + new TemperatureSourceData(SourceNct67Xxd.AUXTIN2, 0x07D, 0x07E, 7, 0xA00, 0x494), + new TemperatureSourceData(SourceNct67Xxd.AUXTIN3, 0x4A0, 0x49E, 6, 0xB00, 0x495), + new TemperatureSourceData(SourceNct67Xxd.AUXTIN4, 0x027,0, 7, 0x621), + new TemperatureSourceData(SourceNct67Xxd.SMBUSMASTER0, 0x150, 0x151, -1, 0x622), + new TemperatureSourceData(SourceNct67Xxd.SMBUSMASTER1, 0x670, 0, -1, 0xC26), + new TemperatureSourceData(SourceNct67Xxd.PECI_1, 0x672, 0, -1, 0xC27), + new TemperatureSourceData(SourceNct67Xxd.PCH_CHIP_CPU_MAX_TEMP, 0x674, 0, -1, 0xC28, 0x400), + new TemperatureSourceData(SourceNct67Xxd.PCH_CHIP_TEMP, 0x676, 0, -1, 0xC29, 0x401), + new TemperatureSourceData(SourceNct67Xxd.PCH_CPU_TEMP, 0x678, 0, -1, 0xC2A, 0x402), + new TemperatureSourceData(SourceNct67Xxd.PCH_MCH_TEMP, 0x67A, 0, -1, 0xC2B, 0x404), + new TemperatureSourceData(SourceNct67Xxd.AGENT0_DIMM0, 0), + new TemperatureSourceData(SourceNct67Xxd.AGENT0_DIMM1, 0), + new TemperatureSourceData(SourceNct67Xxd.AGENT1_DIMM0, 0), + new TemperatureSourceData(SourceNct67Xxd.AGENT1_DIMM1, 0), + new TemperatureSourceData(SourceNct67Xxd.BYTE_TEMP0, 0), + new TemperatureSourceData(SourceNct67Xxd.BYTE_TEMP1, 0), + new TemperatureSourceData(SourceNct67Xxd.PECI_0_CAL, 0), + new TemperatureSourceData(SourceNct67Xxd.PECI_1_CAL, 0), + new TemperatureSourceData(SourceNct67Xxd.VIRTUAL_TEMP, 0) + }); - _temperatureRegister = new ushort[] + if (chip == Chip.NCT6798D) { - 0x073, 0x075, 0x077, 0x079, 0x07B, 0x07D, 0x4A0, 0x027, 0x150, 0x670, 0x672, 0x674, 0x676, 0x678, 0x67A - }; - _temperatureHalfRegister = new ushort[] - { - 0x074, 0x076, 0x078, 0x07A, 0x07C, 0x07E, 0x49E, 0, 0x151, 0, 0, 0, 0, 0, 0 - }; - _temperatureHalfBit = new[] - { - 7, 7, 7, 7, 7, 7, 6, -1, 7, -1, -1, -1, -1, -1, -1 - }; - _temperatureSourceRegister = new ushort[] - { - 0x100, 0x200, 0x300, 0x800, 0x900, 0xA00, 0xB00, 0x621, 0x622, 0xC26, 0xC27, 0xC28, 0xC29, 0xC2A, 0xC2B - }; - _alternateTemperatureRegister = new ushort?[] - { - null, 0x491, 0x490, 0x492, 0x493, 0x494, 0x495, null, null, null, null, 0x400, 0x401, 0x402, 0x404, null, null, null, null, null, null, null, null, null - }; + temperaturesSources.AddRange(new TemperatureSourceData[] + { + new TemperatureSourceData(SourceNct67Xxd.WATER_IN, 0xC33), + new TemperatureSourceData(SourceNct67Xxd.WATER_OUT, 0xC39) + }); + } break; } default: { - Temperatures = new float?[7]; - _temperaturesSource = new Enum[] + temperaturesSources.AddRange(new TemperatureSourceData[] { - SourceNct67Xxd.PECI_0, - SourceNct67Xxd.CPUTIN, - SourceNct67Xxd.SYSTIN, - SourceNct67Xxd.AUXTIN0, - SourceNct67Xxd.AUXTIN1, - SourceNct67Xxd.AUXTIN2, - SourceNct67Xxd.AUXTIN3 - }; - - _temperatureRegister = new ushort[] { 0x027, 0x073, 0x075, 0x077, 0x079, 0x07B, 0x150 }; - _temperatureHalfRegister = new ushort[] { 0, 0x074, 0x076, 0x078, 0x07A, 0x07C, 0x151 }; - _temperatureHalfBit = new[] { -1, 7, 7, 7, 7, 7, 7 }; - _temperatureSourceRegister = new ushort[] { 0x621, 0x100, 0x200, 0x300, 0x800, 0x900, 0x622 }; - _alternateTemperatureRegister = new ushort?[] { null, 0x491, 0x490, 0x492, 0x493, 0x494, 0x495 }; + new TemperatureSourceData(SourceNct67Xxd.PECI_0, 0x027, 0, -1, 0x621), + new TemperatureSourceData(SourceNct67Xxd.CPUTIN, 0x073, 0x074, 7, 0x100, 0x491), + new TemperatureSourceData(SourceNct67Xxd.SYSTIN, 0x075, 0x076, 7, 0x200, 0x490), + new TemperatureSourceData(SourceNct67Xxd.AUXTIN0, 0x077, 0x078, 7, 0x300, 0x492), + new TemperatureSourceData(SourceNct67Xxd.AUXTIN1, 0x079, 0x07A, 7, 0x800, 0x493), + new TemperatureSourceData(SourceNct67Xxd.AUXTIN2, 0x07B, 0x07C, 7, 0x900, 0x494), + new TemperatureSourceData(SourceNct67Xxd.AUXTIN3, 0x150, 0x151, 7, 0x622, 0x495) + }); break; } } + _temperaturesSource = temperaturesSources.ToArray(); + Temperatures = new float?[_temperaturesSource.Length]; break; } case Chip.NCT610XD: @@ -270,14 +270,12 @@ namespace LibreHardwareMonitor.Hardware.Motherboard.Lpc _voltageRegisters = new ushort[] { 0x300, 0x301, 0x302, 0x303, 0x304, 0x305, 0x307, 0x308, 0x309 }; _voltageVBatRegister = 0x308; Temperatures = new float?[4]; - _temperaturesSource = new Enum[] { SourceNct610X.PECI_0, SourceNct610X.SYSTIN, SourceNct610X.CPUTIN, SourceNct610X.AUXTIN }; - - _temperatureRegister = new ushort[] { 0x027, 0x018, 0x019, 0x01A }; - _temperatureHalfRegister = new ushort[] { 0, 0x01B, 0x11B, 0x21B }; - _temperatureHalfBit = new[] { -1, 7, 7, 7 }; - _temperatureSourceRegister = new ushort[] { 0x621, 0x100, 0x200, 0x300 }; - _alternateTemperatureRegister = new ushort?[] { null, 0x018, 0x019, 0x01A }; - + _temperaturesSource = new TemperatureSourceData[] { + new TemperatureSourceData(SourceNct610X.PECI_0, 0x027, 0, -1, 0x621), + new TemperatureSourceData(SourceNct610X.SYSTIN, 0x018, 0x01B, 7, 0x100, 0x018), + new TemperatureSourceData(SourceNct610X.CPUTIN, 0x019, 0x11B, 7, 0x200, 0x019), + new TemperatureSourceData(SourceNct610X.AUXTIN, 0x01A, 0x21B, 7, 0x300, 0x01A) + }; break; } case Chip.NCT6683D: @@ -295,7 +293,15 @@ namespace LibreHardwareMonitor.Hardware.Motherboard.Lpc // CPU Socket // PCIE_1 // M2_1 - _temperatureRegister = new ushort[] { 0x100, 0x102, 0x104, 0x106, 0x108, 0x10A, 0x10C }; + _temperaturesSource = new TemperatureSourceData[] { + new TemperatureSourceData(null, 0x100), + new TemperatureSourceData(null, 0x102), + new TemperatureSourceData(null, 0x104), + new TemperatureSourceData(null, 0x106), + new TemperatureSourceData(null, 0x108), + new TemperatureSourceData(null, 0x10A), + new TemperatureSourceData(null, 0x10C), + }; // VIN0 +12V // VIN1 +5V @@ -342,8 +348,6 @@ namespace LibreHardwareMonitor.Hardware.Motherboard.Lpc WriteByte(0x1BE, 0x64); WriteByte(0x1BF, 0x65); - _alternateTemperatureRegister = new ushort?[] { }; - break; } } @@ -469,15 +473,16 @@ namespace LibreHardwareMonitor.Hardware.Motherboard.Lpc System.Diagnostics.Debug.WriteLine("Updating temperatures."); long temperatureSourceMask = 0; - for (int i = 0; i < _temperatureRegister.Length ; i++) + for (int i = 0; i < _temperaturesSource.Length ; i++) { + TemperatureSourceData ts = _temperaturesSource[i]; switch (Chip) { case Chip.NCT6687D: case Chip.NCT6683D: { - int value = (sbyte)ReadByte(_temperatureRegister[i]); - int half = (ReadByte((ushort)(_temperatureRegister[i] + 1)) >> 7) & 0x1; + int value = (sbyte)ReadByte(ts.Register); + int half = (ReadByte((ushort)(ts.Register + 1)) >> 7) & 0x1; float temperature = value + (0.5f * half); Temperatures[i] = temperature; break; @@ -487,29 +492,29 @@ namespace LibreHardwareMonitor.Hardware.Motherboard.Lpc case Chip.NCT6797D: case Chip.NCT6798D: { - if (_temperatureRegister[i] == 0) + if (_temperaturesSource[i].Register == 0) { System.Diagnostics.Debug.WriteLine("Temperature register {0} skipped, address 0.", i); continue; } - int value = (sbyte)ReadByte(_temperatureRegister[i]) << 1; - System.Diagnostics.Debug.WriteLine("Temperature register {0} at 0x{1:X3} value (integer): {2}/2", i, _temperatureRegister[i], value); - if (_temperatureHalfBit[i] > 0) + int value = (sbyte)ReadByte(_temperaturesSource[i].Register) << 1; + System.Diagnostics.Debug.WriteLine("Temperature register {0} at 0x{1:X3} value (integer): {2}/2", i, ts.Register, value); + if (_temperaturesSource[i].HalfBit > 0) { - value |= (ReadByte(_temperatureHalfRegister[i]) >> _temperatureHalfBit[i]) & 0x1; - System.Diagnostics.Debug.WriteLine("Temperature register {0} value updated from 0x{1:X3} (fractional): {2}/2", i, _temperatureHalfRegister[i], value); + value |= (ReadByte(_temperaturesSource[i].HalfRegister) >> ts.HalfBit) & 0x1; + System.Diagnostics.Debug.WriteLine("Temperature register {0} value updated from 0x{1:X3} (fractional): {2}/2", i, ts.HalfRegister, value); } SourceNct67Xxd source; - if (_temperatureSourceRegister[i] > 0) + if (ts.SourceRegister > 0) { - source = (SourceNct67Xxd)(ReadByte(_temperatureSourceRegister[i]) & 0x1F); - System.Diagnostics.Debug.WriteLine("Temperature register {0} source at 0x{1:X3}: {2:G} ({2:D})", i, _temperatureSourceRegister[i], source); + source = (SourceNct67Xxd)(ReadByte(ts.SourceRegister) & 0x1F); + System.Diagnostics.Debug.WriteLine("Temperature register {0} source at 0x{1:X3}: {2:G} ({2:D})", i, ts.SourceRegister, source); } else { - source = (SourceNct67Xxd)_temperaturesSource[i]; + source = (SourceNct67Xxd)ts.Source; System.Diagnostics.Debug.WriteLine("Temperature register {0} source register is 0, source set to: {1:G} ({1:D})", i, source); } @@ -534,23 +539,23 @@ namespace LibreHardwareMonitor.Hardware.Motherboard.Lpc for (int j = 0; j < Temperatures.Length; j++) { - if ((SourceNct67Xxd)_temperaturesSource[j] == source) + if ((SourceNct67Xxd)_temperaturesSource[j].Source == source) { Temperatures[j] = temperature; - System.Diagnostics.Debug.WriteLine("Temperature register {0}, value from source {1:G} ({1:D}), written at position {2}.", i, _temperaturesSource[j], j); + System.Diagnostics.Debug.WriteLine("Temperature register {0}, value from source {1:G} ({1:D}), written at position {2}.", i, _temperaturesSource[j].Source, j); } } break; } default: { - int value = (sbyte)ReadByte(_temperatureRegister[i]) << 1; - if (_temperatureHalfBit[i] > 0) + int value = (sbyte)ReadByte(ts.Register) << 1; + if (ts.HalfBit > 0) { - value |= (ReadByte(_temperatureHalfRegister[i]) >> _temperatureHalfBit[i]) & 0x1; + value |= (ReadByte(ts.HalfRegister) >> ts.HalfBit) & 0x1; } - SourceNct67Xxd source = (SourceNct67Xxd)ReadByte(_temperatureSourceRegister[i]); + SourceNct67Xxd source = (SourceNct67Xxd)ReadByte(ts.SourceRegister); temperatureSourceMask |= 1L << (byte)source; float? temperature = 0.5f * value; @@ -559,7 +564,7 @@ namespace LibreHardwareMonitor.Hardware.Motherboard.Lpc for (int j = 0; j < Temperatures.Length; j++) { - if ((SourceNct67Xxd)_temperaturesSource[j] == source) + if ((SourceNct67Xxd)_temperaturesSource[j].Source == source) Temperatures[j] = temperature; } break; @@ -567,28 +572,29 @@ namespace LibreHardwareMonitor.Hardware.Motherboard.Lpc } } - for (int i = 0; i < _alternateTemperatureRegister.Length; i++) + for (int i = 0; i < _temperaturesSource.Length; i++) { - if (!_alternateTemperatureRegister[i].HasValue) + TemperatureSourceData ts = _temperaturesSource[i]; + if (!ts.AlternateRegister.HasValue) { - System.Diagnostics.Debug.WriteLine("Alternate temperature register for temperature {0}, {1:G} ({1:D}), skipped, because address is null.", i, _temperaturesSource[i]); + System.Diagnostics.Debug.WriteLine("Alternate temperature register for temperature {0}, {1:G} ({1:D}), skipped, because address is null.", i, ts.Source); continue; } - if ((temperatureSourceMask & (1L << (byte)(SourceNct67Xxd)_temperaturesSource[i])) > 0) + if ((temperatureSourceMask & (1L << (byte)(SourceNct67Xxd)ts.Source)) > 0) { - System.Diagnostics.Debug.WriteLine("Alternate temperature register for temperature {0}, {1:G} ({1:D}), at 0x{2:X3} skipped, because value already set.", i, _temperaturesSource[i], _alternateTemperatureRegister[i].Value); + System.Diagnostics.Debug.WriteLine("Alternate temperature register for temperature {0}, {1:G} ({1:D}), at 0x{2:X3} skipped, because value already set.", i, ts.Source, ts.AlternateRegister.Value); continue; } - float? temperature = (sbyte)ReadByte(_alternateTemperatureRegister[i].Value); - System.Diagnostics.Debug.WriteLine("Alternate temperature register for temperature {0}, {1:G} ({1:D}), at 0x{2:X3} final temperature: {3}.", i, _temperaturesSource[i], _alternateTemperatureRegister[i].Value, temperature); + float? temperature = (sbyte)ReadByte(ts.AlternateRegister.Value); + System.Diagnostics.Debug.WriteLine("Alternate temperature register for temperature {0}, {1:G} ({1:D}), at 0x{2:X3} final temperature: {3}.", i, ts.Source, ts.AlternateRegister.Value, temperature); if (temperature > 125 || temperature <= 0) { temperature = null; - System.Diagnostics.Debug.WriteLine("Alternate Temperature register for temperature {0}, {1:G} ({1:D}), discarded: Out of range.", i, _temperaturesSource[i]); + System.Diagnostics.Debug.WriteLine("Alternate Temperature register for temperature {0}, {1:G} ({1:D}), discarded: Out of range.", i, ts.Source); } Temperatures[i] = temperature; @@ -984,7 +990,9 @@ namespace LibreHardwareMonitor.Hardware.Motherboard.Lpc BYTE_TEMP1 = 27, PECI_0_CAL = 28, PECI_1_CAL = 29, - VIRTUAL_TEMP = 31 + VIRTUAL_TEMP = 31, + WATER_IN = 32, + WATER_OUT = 33 } [SuppressMessage("ReSharper", "InconsistentNaming")] diff --git a/LibreHardwareMonitorLib/Hardware/Motherboard/Model.cs b/LibreHardwareMonitorLib/Hardware/Motherboard/Model.cs index be95978..328da78 100644 --- a/LibreHardwareMonitorLib/Hardware/Motherboard/Model.cs +++ b/LibreHardwareMonitorLib/Hardware/Motherboard/Model.cs @@ -37,6 +37,7 @@ namespace LibreHardwareMonitor.Hardware.Motherboard // ASUS CROSSHAIR_III_FORMULA, + ROG_CROSSHAIR_VIII_HERO, ROG_STRIX_X470_I, M2N_SLI_Deluxe, M4A79XTD_EVO, diff --git a/LibreHardwareMonitorLib/Hardware/Motherboard/Motherboard.cs b/LibreHardwareMonitorLib/Hardware/Motherboard/Motherboard.cs index 0a81806..fee3091 100644 --- a/LibreHardwareMonitorLib/Hardware/Motherboard/Motherboard.cs +++ b/LibreHardwareMonitorLib/Hardware/Motherboard/Motherboard.cs @@ -8,6 +8,8 @@ using System; using System.Collections.Generic; using System.Text; using LibreHardwareMonitor.Hardware.Motherboard.Lpc; +using LibreHardwareMonitor.Hardware.Motherboard.Lpc.EC; +using OperatingSystem = LibreHardwareMonitor.Software.OperatingSystem; namespace LibreHardwareMonitor.Hardware.Motherboard { @@ -49,7 +51,7 @@ namespace LibreHardwareMonitor.Hardware.Motherboard _customName = settings.GetValue(new Identifier(Identifier, "name").ToString(), _name); - if (Software.OperatingSystem.IsUnix) + if (OperatingSystem.IsUnix) { _lmSensors = new LMSensors(); superIO = _lmSensors.SuperIO; @@ -60,11 +62,22 @@ namespace LibreHardwareMonitor.Hardware.Motherboard superIO = _lpcIO.SuperIO; } - SubHardware = new IHardware[superIO.Count]; + EmbeddedController embeddedController = CreateEmbeddedController(model, settings); + + SubHardware = new IHardware[superIO.Count + (embeddedController != null ? 1 : 0)]; for (int i = 0; i < superIO.Count; i++) SubHardware[i] = new SuperIOHardware(this, superIO[i], manufacturer, model, settings); + + if (embeddedController != null) + { + SubHardware[superIO.Count] = embeddedController; + } } + public event SensorEventHandler SensorAdded; + + public event SensorEventHandler SensorRemoved; + public HardwareType HardwareType { get { return HardwareType.Motherboard; } @@ -72,7 +85,7 @@ namespace LibreHardwareMonitor.Hardware.Motherboard public Identifier Identifier { - get { return new Identifier("motherboard"); } + get { return new("motherboard"); } } public string Name @@ -105,7 +118,7 @@ namespace LibreHardwareMonitor.Hardware.Motherboard public string GetReport() { - StringBuilder r = new StringBuilder(); + StringBuilder r = new(); r.AppendLine("Motherboard"); r.AppendLine(); @@ -135,10 +148,6 @@ namespace LibreHardwareMonitor.Hardware.Motherboard hardware.Accept(visitor); } - public event SensorEventHandler SensorAdded; - - public event SensorEventHandler SensorRemoved; - public void Close() { _lmSensors?.Close(); @@ -148,5 +157,34 @@ namespace LibreHardwareMonitor.Hardware.Motherboard hardware.Close(); } } + + private static EmbeddedController CreateEmbeddedController(Model model, ISettings settings) + { + var sources = new List(); + + switch (model) + { + case Model.ROG_CROSSHAIR_VIII_HERO: + { + sources.AddRange(new EmbeddedControllerSource[] + { + new("Chipset", 0x3A, SensorType.Temperature, EmbeddedController.ReadByte), + new("CPU", 0x3B, SensorType.Temperature, EmbeddedController.ReadByte), + new("Motherboard", 0x3C, SensorType.Temperature, EmbeddedController.ReadByte), + new("T Sensor", 0x3D, SensorType.Temperature, EmbeddedController.ReadByte), + new("VRM", 0x3E, SensorType.Temperature, EmbeddedController.ReadByte), + new("CPU Opt", 0xB0, SensorType.Fan, EmbeddedController.ReadWordBE), + new("Chipset", 0xB4, SensorType.Fan, EmbeddedController.ReadWordBE), + // TODO: "why 42?" is a silly question, I know, but still, why? On the serious side, it might be 41.6(6) + new("Flow Rate", 0xBC, SensorType.Flow, (ecIO, port) => ecIO.ReadWordBE(port) / 42f * 60f), + new("CPU", 0xF4, SensorType.Current, EmbeddedController.ReadByte) + }); + + break; + } + } + + return sources.Count > 0 ? EmbeddedController.Create(sources, settings) : null; + } } } diff --git a/LibreHardwareMonitorLib/Hardware/Motherboard/SuperIOHardware.cs b/LibreHardwareMonitorLib/Hardware/Motherboard/SuperIOHardware.cs index bda33c4..73599ae 100644 --- a/LibreHardwareMonitorLib/Hardware/Motherboard/SuperIOHardware.cs +++ b/LibreHardwareMonitorLib/Hardware/Motherboard/SuperIOHardware.cs @@ -2313,6 +2313,58 @@ namespace LibreHardwareMonitor.Hardware.Motherboard break; } + case Model.ROG_CROSSHAIR_VIII_HERO: // NCT6798D + { + v.Add(new Voltage("Vcore", 0)); + v.Add(new Voltage("Voltage #2", 1, true)); + v.Add(new Voltage("AVCC", 2, 34, 34)); + v.Add(new Voltage("+3.3V", 3, 34, 34)); + v.Add(new Voltage("Voltage #5", 4, true)); + v.Add(new Voltage("Voltage #6", 5, true)); + v.Add(new Voltage("Voltage #7", 6, true)); + v.Add(new Voltage("3VSB", 7, 34, 34)); + v.Add(new Voltage("VBat", 8, 34, 34)); + v.Add(new Voltage("VTT", 9)); + v.Add(new Voltage("Voltage #11", 10, true)); + v.Add(new Voltage("Voltage #12", 11, true)); + v.Add(new Voltage("Voltage #13", 12, true)); + v.Add(new Voltage("Voltage #14", 13, true)); + v.Add(new Voltage("Voltage #15", 14, true)); + t.Add(new Temperature("PECI 0", 0)); + t.Add(new Temperature("CPU", 1)); + t.Add(new Temperature("Motherboard", 2)); + t.Add(new Temperature("AUX 0", 3)); + t.Add(new Temperature("AUX 1", 4)); + t.Add(new Temperature("AUX 2", 5)); + t.Add(new Temperature("AUX 3", 6)); + t.Add(new Temperature("AUX 4", 7)); + t.Add(new Temperature("SMBus 0", 8)); + t.Add(new Temperature("SMBus 1", 9)); + t.Add(new Temperature("PECI 1", 10)); + t.Add(new Temperature("PCH Chip CPU Max", 11)); + t.Add(new Temperature("PCH Chip", 12)); + t.Add(new Temperature("PCH CPU", 13)); + t.Add(new Temperature("PCH MCH", 14)); + t.Add(new Temperature("Agent 0 DIMM 0", 15)); + t.Add(new Temperature("Agent 0 DIMM 1", 16)); + t.Add(new Temperature("Agent 1 DIMM 0", 17)); + t.Add(new Temperature("Agent 1 DIMM 1", 18)); + t.Add(new Temperature("Device 0", 19)); + t.Add(new Temperature("Device 1", 20)); + 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)); + + for (int i = 0; i < superIO.Controls.Length; i++) + c.Add(new Ctrl("Fan Control #" + (i + 1), i)); + + break; + } default: { v.Add(new Voltage("Vcore", 0));