From a55a7a772e5fee7a91f277b01032dc1e8a225e7c Mon Sep 17 00:00:00 2001 From: Alcolawl Date: Tue, 22 Apr 2025 10:18:02 -0400 Subject: [PATCH] Add support for MSI AM5/LGA1851 Motherboards using the NCT6687D SIO Controller (#1644) * Add Identification Support for 15 new MSI AM5/LGA1851 Motherboards with the NCT6687D SIO Controller * Create dummy chip entry NCT6687DR * Assign NCT6687DR SIO to 15 newly added MSI AM5/LGA1851 Motherboards This also requires passing Motherboard into DetectWinbondFintek() as we want to maintain prior compatibility while also assigning NCT6687DR to the new motherboards * Add proper voltage, fan, and temperature sensor layouts for motherboards assigned the NCT6687DR controller * Add support for NCT6687DR including dedicated fan control function for system fan manipulation NCT6687DRFanCtrl() is only called when chip == NCT6687DR, otherwise legacy control is maintained. This function works by setting the 7-point fan curve of the system fans to the same requested value where the system fan has no choice but to comply * Rectify code style in new functions to follow standards * Update Nct677X.cs --------- Co-authored-by: Alcolawl Co-authored-by: PhyxionNL <7643972+PhyxionNL@users.noreply.github.com> --- .../Hardware/Motherboard/Identification.cs | 32 ++- .../Hardware/Motherboard/Lpc/Chip.cs | 2 + .../Hardware/Motherboard/Lpc/LpcIO.cs | 31 ++- .../Hardware/Motherboard/Lpc/Nct677X.cs | 139 +++++++++++- .../Hardware/Motherboard/Model.cs | 15 +- .../Hardware/Motherboard/SuperIOHardware.cs | 206 ++++++++++++------ 6 files changed, 334 insertions(+), 91 deletions(-) mode change 100644 => 100755 LibreHardwareMonitorLib/Hardware/Motherboard/Model.cs diff --git a/LibreHardwareMonitorLib/Hardware/Motherboard/Identification.cs b/LibreHardwareMonitorLib/Hardware/Motherboard/Identification.cs index 5692c6e..9d3abfe 100755 --- a/LibreHardwareMonitorLib/Hardware/Motherboard/Identification.cs +++ b/LibreHardwareMonitorLib/Hardware/Motherboard/Identification.cs @@ -627,12 +627,40 @@ internal class Identification return Model.X870E_TOMAHAWK_WIFI; case var _ when name.Equals("MPG X870E CARBON WIFI (MS-7E49)", StringComparison.OrdinalIgnoreCase): return Model.X870E_CARBON_WIFI; - case var _ when name.Equals("PRO X870-P WIFI (MS-7E47)", StringComparison.OrdinalIgnoreCase): - return Model.X870_P_WIFI; case var _ when name.Equals("MPG Z890 EDGE TI WIFI (MS-7E19)", StringComparison.OrdinalIgnoreCase): return Model.Z890_EDGE_TI_WIFI; case var _ when name.Equals("X11SWN-E", StringComparison.OrdinalIgnoreCase): return Model.X11SWN_E; + case var _ when name.Equals("PRO B850-P WIFI (MS-7E56)", StringComparison.OrdinalIgnoreCase): + return Model.B850P_PRO_WIFI; + case var _ when name.Equals("B850 GAMING PLUS WIFI (MS-7E56)", StringComparison.OrdinalIgnoreCase): + return Model.B850_GAMING_PLUS_WIFI; + case var _ when name.Equals("MAG B850 TOMAHAWK MAX WIFI (MS-7E62)", StringComparison.OrdinalIgnoreCase): + return Model.B850_TOMAHAWK_MAX_WIFI; + case var _ when name.Equals("X870 GAMING PLUS WIFI (MS-7E47)", StringComparison.OrdinalIgnoreCase): + return Model.X870_GAMING_PLUS_WIFI; + case var _ when name.Equals("MAG X870 TOMAHAWK WIFI (MS-7E51)", StringComparison.OrdinalIgnoreCase): + return Model.X870_TOMAHAWK_WIFI; + case var _ when name.Equals("MAG X870E TOMAHAWK WIFI (MS-7E59)", StringComparison.OrdinalIgnoreCase): + return Model.X870E_TOMAHAWK_WIFI; + case var _ when name.Equals("MEG X870E GODLIKE (MS-7E48)", StringComparison.OrdinalIgnoreCase): + return Model.X870E_GODLIKE; + case var _ when name.Equals("PRO X870-P WIFI (MS-7E47)", StringComparison.OrdinalIgnoreCase): + return Model.X870P_PRO_WIFI; + case var _ when name.Equals("MPG X870E CARBON WIFI (MS-7E49)", StringComparison.OrdinalIgnoreCase): + return Model.X870E_CARBON_WIFI; + case var _ when name.Equals("MPG X870E EDGE TI WIFI (MS-7E59)", StringComparison.OrdinalIgnoreCase): + return Model.X870E_EDGE_TI_WIFI; + case var _ when name.Equals("MEG Z890 ACE (MS-7E22)", StringComparison.OrdinalIgnoreCase): + return Model.Z890_ACE; + case var _ when name.Equals("MAG Z890 TOMAHAWK WIFI (MS-7E32)", StringComparison.OrdinalIgnoreCase): + return Model.Z890_TOMAHAWK_WIFI; + case var _ when name.Equals("MPG Z890 CARBON WIFI (MS-7E17)", StringComparison.OrdinalIgnoreCase): + return Model.Z890_CARBON_WIFI; + case var _ when name.Equals("MPG Z890 EDGE TI WIFI (MS-7E19)", StringComparison.OrdinalIgnoreCase): + return Model.Z890_EDGE_TI_WIFI; + case var _ when name.Equals("PRO Z890-P WIFI (MS-7E34)", StringComparison.OrdinalIgnoreCase): + return Model.Z890P_PRO_WIFI; case var _ when name.Equals("Base Board Product Name", StringComparison.OrdinalIgnoreCase): case var _ when name.Equals("To be filled by O.E.M.", StringComparison.OrdinalIgnoreCase): return Model.Unknown; diff --git a/LibreHardwareMonitorLib/Hardware/Motherboard/Lpc/Chip.cs b/LibreHardwareMonitorLib/Hardware/Motherboard/Lpc/Chip.cs index 653460a..806b483 100755 --- a/LibreHardwareMonitorLib/Hardware/Motherboard/Lpc/Chip.cs +++ b/LibreHardwareMonitorLib/Hardware/Motherboard/Lpc/Chip.cs @@ -67,6 +67,7 @@ internal enum Chip : ushort NCT6798D = 0xD42B, NCT6686D = 0xD440, NCT6687D = 0xD592, + NCT6687DR = 0xFFFF, // Dummy Entry for MSI AM5/LGA1851 Motherboards NCT6683D = 0xC732, NCT6799D = 0xD802, NCT6701D = 0xD806, @@ -142,6 +143,7 @@ internal class ChipName case Chip.NCT6799D: return "Nuvoton NCT6799D"; case Chip.NCT6686D: return "Nuvoton NCT6686D"; case Chip.NCT6687D: return "Nuvoton NCT6687D"; + case Chip.NCT6687DR: return "Nuvoton NCT6687D-R"; case Chip.NCT6683D: return "Nuvoton NCT6683D"; case Chip.NCT6701D: return "Nuvoton NCT6701D"; diff --git a/LibreHardwareMonitorLib/Hardware/Motherboard/Lpc/LpcIO.cs b/LibreHardwareMonitorLib/Hardware/Motherboard/Lpc/LpcIO.cs index b000065..0ec943f 100644 --- a/LibreHardwareMonitorLib/Hardware/Motherboard/Lpc/LpcIO.cs +++ b/LibreHardwareMonitorLib/Hardware/Motherboard/Lpc/LpcIO.cs @@ -67,7 +67,7 @@ internal class LpcIO { var port = new LpcPort(REGISTER_PORTS[i], VALUE_PORTS[i]); - if (DetectWinbondFintek(port)) continue; + if (DetectWinbondFintek(port, motherboard)) continue; if (DetectIT87(port, motherboard)) continue; @@ -85,7 +85,7 @@ internal class LpcIO return null; } - private bool DetectWinbondFintek(LpcPort port) + private bool DetectWinbondFintek(LpcPort port, Motherboard motherboard) { port.WinbondNuvotonFintekEnter(); @@ -389,8 +389,30 @@ internal class LpcIO case 0xD5: switch (revision) { - case 0x92: - chip = Chip.NCT6687D; + case 0x92: + switch (motherboard.Model) + { + case Model.B850_GAMING_PLUS_WIFI: + case Model.B850P_PRO_WIFI: + case Model.B850_TOMAHAWK_MAX_WIFI: + case Model.X870_GAMING_PLUS_WIFI: + case Model.X870_TOMAHAWK_WIFI: + case Model.X870P_PRO_WIFI: + case Model.X870E_TOMAHAWK_WIFI: + case Model.X870E_CARBON_WIFI: + case Model.X870E_EDGE_TI_WIFI: + case Model.X870E_GODLIKE: + case Model.Z890_ACE: + case Model.Z890_CARBON_WIFI: + case Model.Z890_TOMAHAWK_WIFI: + case Model.Z890_EDGE_TI_WIFI: + case Model.Z890P_PRO_WIFI: + chip = Chip.NCT6687DR; // MSI AM5/LGA1851 Compatibility + break; + default: + chip = Chip.NCT6687D; + break; + } logicalDeviceNumber = WINBOND_NUVOTON_HARDWARE_MONITOR_LDN; break; } @@ -496,6 +518,7 @@ internal class LpcIO case Chip.NCT6799D: case Chip.NCT6686D: case Chip.NCT6687D: + case Chip.NCT6687DR: case Chip.NCT6683D: case Chip.NCT6701D: _superIOs.Add(new Nct677X(chip, revision, address, port)); diff --git a/LibreHardwareMonitorLib/Hardware/Motherboard/Lpc/Nct677X.cs b/LibreHardwareMonitorLib/Hardware/Motherboard/Lpc/Nct677X.cs index f500f88..e94c457 100644 --- a/LibreHardwareMonitorLib/Hardware/Motherboard/Lpc/Nct677X.cs +++ b/LibreHardwareMonitorLib/Hardware/Motherboard/Lpc/Nct677X.cs @@ -76,6 +76,13 @@ internal class Nct677X : ISuperIO FAN_CONTROL_MODE_REG = new ushort[] { 0xA00, 0xA00, 0xA00, 0xA00, 0xA00, 0xA00, 0xA00, 0xA00 }; // Not sure of next 8, MSI won't provide info FAN_PWM_REQUEST_REG = new ushort[] { 0xA01, 0xA01, 0xA01, 0xA01, 0xA01, 0xA01, 0xA01, 0xA01 }; // Not sure of next 8, MSI won't provide info } + else if (chip is Chip.NCT6687DR) // MSI AM5/LGA1851 Motherboards + { + FAN_PWM_OUT_REG = new ushort[] { 0x160, 0x161, 0xE05, 0xE04, 0xE03, 0xE02, 0xE01, 0xE00 }; // Duty Cycle Sensors + FAN_PWM_COMMAND_REG = new ushort[] { 0xA28, 0xA29, 0xC70, 0xC58, 0xC40, 0xC28, 0xC10, 0xBF8 }; // Control Registers for CPU/Pump, Initial Fan Curve Registers for System Fans + FAN_CONTROL_MODE_REG = new ushort[] { 0xA00, 0xA00, 0xA00, 0xA00, 0xA00, 0xA00, 0xA00, 0xA00 }; + FAN_PWM_REQUEST_REG = new ushort[] { 0xA01, 0xA01, 0xA01, 0xA01, 0xA01, 0xA01, 0xA01, 0xA01 }; + } else { VENDOR_ID_HIGH_REGISTER = 0x804F; @@ -345,6 +352,68 @@ internal class Nct677X : ISuperIO WriteByte(0x1BE, 0x64); WriteByte(0x1BF, 0x65); break; + + case Chip.NCT6687DR: + Fans = new float?[8]; + Controls = new float?[8]; + Voltages = new float?[14]; + Temperatures = new float?[7]; + + _temperaturesSource = new TemperatureSourceData[] { + new(null, 0x100), // CPU + new(null, 0x102), // System + new(null, 0x104), // MOS + new(null, 0x106), // PCH + new(null, 0x108), // CPU Socket + new(null, 0x10A), // PCIE_1 + new(null, 0x10C) // M2_1 + }; + + // VIN0 +12V + // VIN1 +5V + // VIN2 VCore + // VIN3 SIO + // VIN4 DRAM + // VIN5 CPU IO + // VIN6 CPU SA + // VIN7 SIO + // 3VCC I/O +3.3 + // SIO VTT + // SIO VREF + // SIO VSB + // SIO AVSB + // SIO VBAT + _voltageRegisters = new ushort[] { 0x120, 0x122, 0x124, 0x126, 0x128, 0x12A, 0x12C, 0x12E, 0x130, 0x13A, 0x13E, 0x136, 0x138, 0x13C }; + + // CPU Fan 0x140 + // PUMP Fan 0x142 + // SYS Fan 1 0x15E + // SYS Fan 2 0x15C + // SYS Fan 3 0x15A + // SYS Fan 4 0x158 + // SYS Fan 5 0x156 + // SYS Fan 6 0x154 + _fanRpmRegister = new ushort[] { 0x140, 0x142, 0x15E, 0x15C, 0x15A, 0x158, 0x156, 0x154 }; + + _restoreDefaultFanControlRequired = new bool[_fanRpmRegister.Length]; + _initialFanControlMode = new byte[_fanRpmRegister.Length]; + _initialFanPwmCommand = new byte[_fanRpmRegister.Length]; + + // initialize + const ushort initRegisterNct6687DR = 0x180; + byte dataNct6687DR = ReadByte(initRegisterNct6687DR); + if ((dataNct6687DR & 0x80) == 0) + { + WriteByte(initRegisterNct6687DR, (byte)(dataNct6687DR | 0x80)); + } + + // enable SIO voltage -- address, value + WriteByte(0x1BB, 0x61); + WriteByte(0x1BC, 0x62); + WriteByte(0x1BD, 0x63); + WriteByte(0x1BE, 0x64); + WriteByte(0x1BF, 0x65); + break; } } @@ -381,7 +450,7 @@ internal class Nct677X : ISuperIO { SaveDefaultFanControl(index); - if (Chip is not Chip.NCT6683D and not Chip.NCT6686D and not Chip.NCT6687D) + if (Chip is not Chip.NCT6683D and not Chip.NCT6686D and not Chip.NCT6687D and not Chip.NCT6687DR) { // set manual mode WriteByte(FAN_CONTROL_MODE_REG[index], 0); @@ -409,7 +478,15 @@ internal class Nct677X : ISuperIO WriteByte(FAN_PWM_REQUEST_REG[index], 0x80); Thread.Sleep(50); - WriteByte(FAN_PWM_COMMAND_REG[index], value.Value); + if (Chip is Chip.NCT6687DR) // For MSI AM5/LGA1851 NCT6687D functionality + { + Set6687DRControl(index, value.Value); + } + else // All other Nuvoton SIO controllers and motherboards that use NCT6683/6686/6687 + { + WriteByte(FAN_PWM_COMMAND_REG[index], value.Value); + } + WriteByte(FAN_PWM_REQUEST_REG[index], 0x40); Thread.Sleep(50); } @@ -434,7 +511,7 @@ internal class Nct677X : ISuperIO for (int i = 0; i < Voltages.Length; i++) { - if (Chip is not Chip.NCT6683D and not Chip.NCT6686D and not Chip.NCT6687D) + if (Chip is not Chip.NCT6683D and not Chip.NCT6686D and not Chip.NCT6687D and not Chip.NCT6687DR) { float value = 0.008f * ReadByte(_voltageRegisters[i]); bool valid = value > 0; @@ -481,6 +558,7 @@ internal class Nct677X : ISuperIO break; case Chip.NCT6687D: + case Chip.NCT6687DR: case Chip.NCT6686D: case Chip.NCT6683D: value = (sbyte)ReadByte(ts.Register); @@ -600,7 +678,7 @@ internal class Nct677X : ISuperIO for (int i = 0; i < Fans.Length; i++) { - if (Chip is not Chip.NCT6683D and not Chip.NCT6686D and not Chip.NCT6687D) + if (Chip is not Chip.NCT6683D and not Chip.NCT6686D and not Chip.NCT6687D and not Chip.NCT6687DR) { if (_fanCountRegister != null) { @@ -641,7 +719,7 @@ internal class Nct677X : ISuperIO for (int i = 0; i < Controls.Length; i++) { - if (Chip is not Chip.NCT6683D and not Chip.NCT6686D and not Chip.NCT6687D) + if (Chip is not Chip.NCT6683D and not Chip.NCT6686D and not Chip.NCT6687D and not Chip.NCT6687DR) { int value = ReadByte(FAN_PWM_OUT_REG[i]); Controls[i] = value / 2.55f; @@ -782,7 +860,7 @@ internal class Nct677X : ISuperIO r.AppendLine(" 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F"); r.AppendLine(); - if (Chip is not Chip.NCT6683D and not Chip.NCT6686D and not Chip.NCT6687D) + if (Chip is not Chip.NCT6683D and not Chip.NCT6686D and not Chip.NCT6687D and not Chip.NCT6687DR) { foreach (ushort address in addresses) { @@ -825,7 +903,7 @@ internal class Nct677X : ISuperIO private byte ReadByte(ushort address) { - if (Chip is not Chip.NCT6683D and not Chip.NCT6686D and not Chip.NCT6687D) + if (Chip is not Chip.NCT6683D and not Chip.NCT6686D and not Chip.NCT6687D and not Chip.NCT6687DR) { byte bank = (byte)(address >> 8); byte register = (byte)(address & 0xFF); @@ -870,7 +948,7 @@ internal class Nct677X : ISuperIO private void WriteByte(ushort address, byte value) { - if (Chip is not Chip.NCT6683D and not Chip.NCT6686D and not Chip.NCT6687D) + if (Chip is not Chip.NCT6683D and not Chip.NCT6686D and not Chip.NCT6687D and not Chip.NCT6687DR) { byte bank = (byte)(address >> 8); byte register = (byte)(address & 0xFF); @@ -915,14 +993,45 @@ internal class Nct677X : ISuperIO private bool IsNuvotonVendor() { - return Chip is Chip.NCT6683D or Chip.NCT6686D or Chip.NCT6687D || ((ReadByte(VENDOR_ID_HIGH_REGISTER) << 8) | ReadByte(VENDOR_ID_LOW_REGISTER)) == NUVOTON_VENDOR_ID; + return Chip is Chip.NCT6683D or Chip.NCT6686D or Chip.NCT6687D or Chip.NCT6687DR || ((ReadByte(VENDOR_ID_HIGH_REGISTER) << 8) | ReadByte(VENDOR_ID_LOW_REGISTER)) == NUVOTON_VENDOR_ID; + } + + private void Set6687DRControl(int index, byte? value) + { + if (index > 1) // System Fan Control + { + int initFanCurveReg = FAN_PWM_COMMAND_REG[index]; // Initial Register Address for the Fan Curve + int targetFanCurveAddr = initFanCurveReg; // Address of the Current Fan Curve Register we're writing to + ushort targetFanCurveReg; // Integer value of the current fan curve register address, not the value within + byte currentSpeed = ReadByte(FAN_PWM_OUT_REG[index]); // Current Speed of the target fan + + // If current fan duty cycle matches requested duty cycle, skip re-writing the fan curve + if (currentSpeed == value.Value) + { + return; + } + else + { + // Write 7-point fan curve + for (int count = 0; count < 14; count = count + 2) + { + targetFanCurveAddr = initFanCurveReg+count; + targetFanCurveReg = Convert.ToUInt16(targetFanCurveAddr); + WriteByte(targetFanCurveReg, value.Value); + } + } + } + else // Control CPU and Pump Fan normally + { + WriteByte(FAN_PWM_COMMAND_REG[index], value.Value); + } } private void SaveDefaultFanControl(int index) { if (!_restoreDefaultFanControlRequired[index]) { - if (Chip is not Chip.NCT6683D and not Chip.NCT6686D and not Chip.NCT6687D) + if (Chip is not Chip.NCT6683D and not Chip.NCT6686D and not Chip.NCT6687D and not Chip.NCT6687DR) { _initialFanControlMode[index] = ReadByte(FAN_CONTROL_MODE_REG[index]); } @@ -942,7 +1051,7 @@ internal class Nct677X : ISuperIO { if (_restoreDefaultFanControlRequired[index]) { - if (Chip is not Chip.NCT6683D and not Chip.NCT6686D and not Chip.NCT6687D) + if (Chip is not Chip.NCT6683D and not Chip.NCT6686D and not Chip.NCT6687D and not Chip.NCT6687DR) { WriteByte(FAN_CONTROL_MODE_REG[index], _initialFanControlMode[index]); WriteByte(FAN_PWM_COMMAND_REG[index], _initialFanPwmCommand[index]); @@ -956,7 +1065,13 @@ internal class Nct677X : ISuperIO WriteByte(FAN_PWM_REQUEST_REG[index], 0x80); Thread.Sleep(50); - WriteByte(FAN_PWM_COMMAND_REG[index], _initialFanPwmCommand[index]); + if (Chip is Chip.NCT6687DR) { // for MSI AM5/LGA1851 boards using NCT6687D + Set6687DRControl(index, _initialFanPwmCommand[index]); + } + else { // All other motherboards that use NCT6683/6686/6687 + WriteByte(FAN_PWM_COMMAND_REG[index], _initialFanPwmCommand[index]); + } + WriteByte(FAN_PWM_REQUEST_REG[index], 0x40); Thread.Sleep(50); } diff --git a/LibreHardwareMonitorLib/Hardware/Motherboard/Model.cs b/LibreHardwareMonitorLib/Hardware/Motherboard/Model.cs old mode 100644 new mode 100755 index 6a1fdce..658b4de --- a/LibreHardwareMonitorLib/Hardware/Motherboard/Model.cs +++ b/LibreHardwareMonitorLib/Hardware/Motherboard/Model.cs @@ -136,13 +136,22 @@ public enum Model Z77_MS7751, Z68_MS7672, X570_Gaming_Plus, - X870_TOMAHAWK_WIFI, - Z890_CARBON_WIFI, + B850_GAMING_PLUS_WIFI, + B850_TOMAHAWK_MAX_WIFI, B650M_PROJECT_ZERO, + B850P_PRO_WIFI, + X870_GAMING_PLUS_WIFI, + X870_TOMAHAWK_WIFI, X870E_TOMAHAWK_WIFI, + X870E_GODLIKE, + X870P_PRO_WIFI, X870E_CARBON_WIFI, - X870_P_WIFI, + X870E_EDGE_TI_WIFI, + Z890_ACE, + Z890_TOMAHAWK_WIFI, + Z890_CARBON_WIFI, Z890_EDGE_TI_WIFI, + Z890P_PRO_WIFI, // EVGA X58_SLI_Classified, diff --git a/LibreHardwareMonitorLib/Hardware/Motherboard/SuperIOHardware.cs b/LibreHardwareMonitorLib/Hardware/Motherboard/SuperIOHardware.cs index 637db54..1846c04 100755 --- a/LibreHardwareMonitorLib/Hardware/Motherboard/SuperIOHardware.cs +++ b/LibreHardwareMonitorLib/Hardware/Motherboard/SuperIOHardware.cs @@ -483,76 +483,6 @@ internal sealed class SuperIOHardware : Hardware break; - case Manufacturer.MSI when model == Model.X870_TOMAHAWK_WIFI: //NCT6687D with 9 fans - case Manufacturer.MSI when model == Model.X870_TOMAHAWK_WIFI: - case Manufacturer.MSI when model == Model.Z890_CARBON_WIFI: - case Manufacturer.MSI when model == Model.X870E_TOMAHAWK_WIFI: - case Manufacturer.MSI when model == Model.X870E_CARBON_WIFI: - case Manufacturer.MSI when model == Model.X870_P_WIFI: - case Manufacturer.MSI when model == Model.Z890_EDGE_TI_WIFI: - v.Add(new Voltage("+12V", 0)); - v.Add(new Voltage("+5V", 1)); - v.Add(new Voltage("CPU Northbridge/SoC", 2)); - v.Add(new Voltage("VDDIO", 3, 1, 1, 0)); - v.Add(new Voltage("Vcore", 4, -1, 2, 0)); - v.Add(new Voltage("+3.3V", 8)); - v.Add(new Voltage("+3V Standby", 11)); - v.Add(new Voltage("AVSB", 12)); - v.Add(new Voltage("CPU Termination", 9)); - v.Add(new Voltage("CMOS Battery", 13)); - - t.Add(new Temperature("CPU", 0)); - t.Add(new Temperature("System", 1)); - t.Add(new Temperature("VRM MOS", 2)); - t.Add(new Temperature("Chipset A", 3)); - - f.Add(new Fan("CPU Fan", 0)); - f.Add(new Fan("Pump Fan", 1)); - f.Add(new Fan("EZConn Fan", 3)); - f.Add(new Fan("System Fan #6", 10)); - f.Add(new Fan("System Fan #5", 11)); - f.Add(new Fan("System Fan #4", 12)); - f.Add(new Fan("System Fan #3", 13)); - f.Add(new Fan("System Fan #2", 14)); - f.Add(new Fan("System Fan #1", 15)); - - c.Add(new Control("CPU Fan", 0)); - c.Add(new Control("Pump Fan", 1)); - c.Add(new Control("EZConn Fan", 3)); - break; - - case Manufacturer.MSI when model == Model.Z890_CARBON_WIFI: //NCT6687D with 8 fans - case Manufacturer.MSI when model == Model.X870E_CARBON_WIFI: - v.Add(new Voltage("+12V", 0)); - v.Add(new Voltage("+5V", 1)); - v.Add(new Voltage("CPU Northbridge/SoC", 2)); - v.Add(new Voltage("VDDIO", 3, 1, 1, 0)); - v.Add(new Voltage("Vcore", 4, -1, 2, 0)); - v.Add(new Voltage("+3.3V", 8)); - v.Add(new Voltage("+3V Standby", 11)); - v.Add(new Voltage("AVSB", 12)); - v.Add(new Voltage("CPU Termination", 9)); - v.Add(new Voltage("CMOS Battery", 13)); - - t.Add(new Temperature("CPU", 0)); - t.Add(new Temperature("System", 1)); - t.Add(new Temperature("VRM MOS", 2)); - t.Add(new Temperature("Chipset A", 3)); - - f.Add(new Fan("CPU Fan", 0)); - f.Add(new Fan("Pump Fan", 1)); - f.Add(new Fan("EZConn Fan", 3)); - f.Add(new Fan("System Fan #5", 11)); - f.Add(new Fan("System Fan #4", 12)); - f.Add(new Fan("System Fan #3", 13)); - f.Add(new Fan("System Fan #2", 14)); - f.Add(new Fan("System Fan #1", 15)); - - c.Add(new Control("CPU Fan", 0)); - c.Add(new Control("Pump Fan", 1)); - c.Add(new Control("EZConn Fan", 3)); - break; - default: v.Add(new Voltage("+12V", 0)); v.Add(new Voltage("+5V", 1)); @@ -600,6 +530,142 @@ internal sealed class SuperIOHardware : Hardware break; + case Chip.NCT6687DR: + + // Universal Sensor and Control defaults + t.Add(new Temperature("CPU Core", 0)); + t.Add(new Temperature("System", 1)); + t.Add(new Temperature("VRM MOS", 2)); + t.Add(new Temperature("Chipset", 3)); + + f.Add(new Fan("CPU Fan", 0)); + f.Add(new Fan("Pump Fan #1", 1)); + f.Add(new Fan("System Fan #1", 2)); + f.Add(new Fan("System Fan #2", 3)); + f.Add(new Fan("System Fan #3", 4)); + f.Add(new Fan("System Fan #4", 5)); + f.Add(new Fan("System Fan #5", 6)); + f.Add(new Fan("System Fan #6", 7)); + + c.Add(new Control("CPU Fan", 0)); + c.Add(new Control("Pump Fan", 1)); + c.Add(new Control("System Fan #1", 2)); + c.Add(new Control("System Fan #2", 3)); + c.Add(new Control("System Fan #3", 4)); + c.Add(new Control("System Fan #4", 5)); + c.Add(new Control("System Fan #5", 6)); + c.Add(new Control("System Fan #6", 7)); + + switch (model) + { + case Model.X870E_TOMAHAWK_WIFI: + case Model.X870E_EDGE_TI_WIFI: + v.Add(new Voltage("+12V", 0)); + v.Add(new Voltage("+5V", 1)); + v.Add(new Voltage("CPU Northbridge/SoC", 2)); + v.Add(new Voltage("DIMM", 3, 1, 1)); + v.Add(new Voltage("Vcore", 4, -1, 2)); + v.Add(new Voltage("Chipset", 5)); + v.Add(new Voltage("CPU System Agent", 6)); + //v.Add(new Voltage("Unknown_4", 7)); //"Voltage #2" + v.Add(new Voltage("+3.3V", 8)); + v.Add(new Voltage("VREF", 9)); + v.Add(new Voltage("+1.8V", 10)); + v.Add(new Voltage("+3V Standby", 11)); + v.Add(new Voltage("AVSB", 12)); + v.Add(new Voltage("CMOS Battery", 13)); + + t.Add(new Temperature("CPU Socket", 4)); + + break; + + case Model.X870E_CARBON_WIFI: + case Model.X870E_GODLIKE: + v.Add(new Voltage("+12V", 0)); + v.Add(new Voltage("+5V", 1)); + v.Add(new Voltage("CPU Northbridge/SoC", 2)); + v.Add(new Voltage("DIMM", 3, 1, 1)); + v.Add(new Voltage("Vcore", 4, -1, 2)); + v.Add(new Voltage("Chipset", 5)); + v.Add(new Voltage("CPU System Agent", 6)); + //v.Add(new Voltage("Unknown_4", 7)); //"Voltage #2" + v.Add(new Voltage("+3.3V", 8)); + v.Add(new Voltage("VREF", 9)); + v.Add(new Voltage("+1.8V", 10)); + v.Add(new Voltage("+3V Standby", 11)); + v.Add(new Voltage("AVSB", 12)); + v.Add(new Voltage("CMOS Battery", 13)); + + t.Add(new Temperature("PCIe x1", 5)); + t.Add(new Temperature("M2_1", 6)); + + break; + + case Model.Z890_CARBON_WIFI: + case Model.Z890_TOMAHAWK_WIFI: + case Model.Z890_ACE: + v.Add(new Voltage("+12V", 0)); + v.Add(new Voltage("+5V", 1)); + v.Add(new Voltage("Vcore", 2)); + v.Add(new Voltage("VIN5", 3)); + v.Add(new Voltage("VDIMM", 4)); + v.Add(new Voltage("Chipset", 5)); + //v.Add(new Voltage("CPU System Agent", 6)); + v.Add(new Voltage("VIN7", 7)); + v.Add(new Voltage("+3.3V", 8)); + v.Add(new Voltage("VTT", 9)); + v.Add(new Voltage("+1.8V", 10)); + v.Add(new Voltage("+3V Standby", 11)); + v.Add(new Voltage("AVSB", 12)); + v.Add(new Voltage("CMOS Battery", 13)); + + t.Add(new Temperature("CPU Socket", 4)); + t.Add(new Temperature("PCIe x1", 5)); + t.Add(new Temperature("M2_1", 6)); + + break; + + case Model.Z890_EDGE_TI_WIFI: + case Model.Z890P_PRO_WIFI: + v.Add(new Voltage("+12V", 0)); + v.Add(new Voltage("+5V", 1)); + v.Add(new Voltage("Vcore", 2)); + v.Add(new Voltage("VIN5", 3)); + v.Add(new Voltage("VDIMM", 4)); + v.Add(new Voltage("Chipset", 5)); + //v.Add(new Voltage("CPU System Agent", 6)); + v.Add(new Voltage("Unknown_3", 7)); + v.Add(new Voltage("+3.3V", 8)); + v.Add(new Voltage("VTT", 9)); + v.Add(new Voltage("+1.8V", 10)); + v.Add(new Voltage("+3V Standby", 11)); + v.Add(new Voltage("AVSB", 12)); + v.Add(new Voltage("CMOS Battery", 13)); + + break; + + default: + v.Add(new Voltage("+12V", 0)); + v.Add(new Voltage("+5V", 1)); + v.Add(new Voltage("CPU Northbridge/SoC", 2)); + v.Add(new Voltage("DIMM", 3, 1, 1)); + v.Add(new Voltage("Vcore", 4, -1, 2)); + v.Add(new Voltage("Chipset", 5)); + v.Add(new Voltage("CPU System Agent", 6)); + //v.Add(new Voltage("Unknown_4", 7)); //"Voltage #2" + v.Add(new Voltage("+3.3V", 8)); + v.Add(new Voltage("VREF", 9)); + v.Add(new Voltage("+1.8V", 10)); + v.Add(new Voltage("+3V Standby", 11)); + v.Add(new Voltage("AVSB", 12)); + v.Add(new Voltage("CMOS Battery", 13)); + + break; + + } + + break; + case Chip.IPMI: Ipmi ipmi = (Ipmi)superIO;