@@ -18,7 +18,8 @@ namespace LibreHardwareMonitor.Hardware
|
||||
GpuAmd,
|
||||
Storage,
|
||||
Network,
|
||||
Cooler
|
||||
Cooler,
|
||||
EmbeddedController
|
||||
}
|
||||
|
||||
public interface IHardware : IElement
|
||||
|
||||
@@ -12,6 +12,7 @@ namespace LibreHardwareMonitor.Hardware
|
||||
public enum SensorType
|
||||
{
|
||||
Voltage, // V
|
||||
Current, // A
|
||||
Clock, // MHz
|
||||
Temperature, // °C
|
||||
Load, // %
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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<EmbeddedControllerSensor> _sensors;
|
||||
|
||||
protected EmbeddedController(List<EmbeddedControllerSource> sources, ISettings settings) : base("Embedded Controller", new Identifier("lpc", "ec"), settings)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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<EmbeddedControllerSource> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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; }
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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<EmbeddedControllerSource> sources, ISettings settings) : base(sources, settings)
|
||||
{ }
|
||||
|
||||
protected override IEmbeddedControllerIO AcquireIOInterface()
|
||||
{
|
||||
return new WindowsEmbeddedControllerIO();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// An unsafe but universal implementation for the ACPI Embedded Controller IO interface for Windows
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 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.
|
||||
/// </remarks>
|
||||
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<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)
|
||||
{
|
||||
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<TResult>(byte register, ReadOp<TResult> 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<TValue>(byte register, TValue value, WriteOp<TValue> 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<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())
|
||||
{
|
||||
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
|
||||
}
|
||||
}
|
||||
@@ -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<TemperatureSourceData>();
|
||||
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")]
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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<EmbeddedControllerSource>();
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
|
||||
Reference in New Issue
Block a user