# HG changeset patch # User moel.mich # Date 1290360685 0 # Node ID f8e72b2efcc028f95a5836cb3604217308539baa # Parent 99f16e21cdc85803bb3bfecd593e23c9346f1121 Added first experimental support for the Nuvoton NCT6771F super I/O chip. diff -r 99f16e21cdc8 -r f8e72b2efcc0 Hardware/LPC/Chip.cs --- a/Hardware/LPC/Chip.cs Sun Nov 21 12:28:31 2010 +0000 +++ b/Hardware/LPC/Chip.cs Sun Nov 21 17:31:25 2010 +0000 @@ -53,12 +53,13 @@ W83667HG = 0xA510, W83667HGB = 0xB350, W83687THF = 0x8541, + NCT6771F = 0xB470, F71858 = 0x0507, F71862 = 0x0601, F71869 = 0x0814, F71882 = 0x0541, F71889ED = 0x0909, - F71889F = 0x0723 + F71889F = 0x0723 } internal class ChipName { @@ -87,6 +88,7 @@ case Chip.W83667HG: return "Winbond W83667HG"; case Chip.W83667HGB: return "Winbond W83667HG-B"; case Chip.W83687THF: return "Winbond W83687THF"; + case Chip.NCT6771F: return "Nuvoton NCT6771F"; case Chip.Unknown: return "Unkown"; default: return "Unknown"; } diff -r 99f16e21cdc8 -r f8e72b2efcc0 Hardware/LPC/LPCIO.cs --- a/Hardware/LPC/LPCIO.cs Sun Nov 21 12:28:31 2010 +0000 +++ b/Hardware/LPC/LPCIO.cs Sun Nov 21 17:31:25 2010 +0000 @@ -88,27 +88,27 @@ report.AppendLine(); } - #region Winbond, Fintek + #region Winbond, Nuvoton, Fintek private const byte FINTEK_VENDOR_ID_REGISTER = 0x23; private const ushort FINTEK_VENDOR_ID = 0x1934; - private const byte WINBOND_HARDWARE_MONITOR_LDN = 0x0B; + private const byte WINBOND_NUVOTON_HARDWARE_MONITOR_LDN = 0x0B; private const byte F71858_HARDWARE_MONITOR_LDN = 0x02; private const byte FINTEK_HARDWARE_MONITOR_LDN = 0x04; - private void WinbondFintekEnter() { + private void WinbondNuvotonFintekEnter() { Ring0.WriteIoPort(registerPort, 0x87); Ring0.WriteIoPort(registerPort, 0x87); } - private void WinbondFintekExit() { + private void WinbondNuvotonFintekExit() { Ring0.WriteIoPort(registerPort, 0xAA); } private bool DetectWinbondFintek() { - WinbondFintekEnter(); + WinbondNuvotonFintekEnter(); byte logicalDeviceNumber = 0; byte id = ReadByte(CHIP_ID_REGISTER); @@ -160,21 +160,21 @@ case 0x3A: case 0x41: chip = Chip.W83627HF; - logicalDeviceNumber = WINBOND_HARDWARE_MONITOR_LDN; + logicalDeviceNumber = WINBOND_NUVOTON_HARDWARE_MONITOR_LDN; break; } break; case 0x82: switch (revision & 0xF0) { case 0x80: chip = Chip.W83627THF; - logicalDeviceNumber = WINBOND_HARDWARE_MONITOR_LDN; + logicalDeviceNumber = WINBOND_NUVOTON_HARDWARE_MONITOR_LDN; break; } break; case 0x85: switch (revision) { case 0x41: chip = Chip.W83687THF; - logicalDeviceNumber = WINBOND_HARDWARE_MONITOR_LDN; + logicalDeviceNumber = WINBOND_NUVOTON_HARDWARE_MONITOR_LDN; break; } break; case 0x88: @@ -182,43 +182,51 @@ case 0x50: case 0x60: chip = Chip.W83627EHF; - logicalDeviceNumber = WINBOND_HARDWARE_MONITOR_LDN; + logicalDeviceNumber = WINBOND_NUVOTON_HARDWARE_MONITOR_LDN; break; } break; case 0xA0: switch (revision & 0xF0) { case 0x20: chip = Chip.W83627DHG; - logicalDeviceNumber = WINBOND_HARDWARE_MONITOR_LDN; + logicalDeviceNumber = WINBOND_NUVOTON_HARDWARE_MONITOR_LDN; break; } break; case 0xA5: switch (revision & 0xF0) { case 0x10: chip = Chip.W83667HG; - logicalDeviceNumber = WINBOND_HARDWARE_MONITOR_LDN; + logicalDeviceNumber = WINBOND_NUVOTON_HARDWARE_MONITOR_LDN; break; } break; case 0xB0: switch (revision & 0xF0) { case 0x70: chip = Chip.W83627DHGP; - logicalDeviceNumber = WINBOND_HARDWARE_MONITOR_LDN; + logicalDeviceNumber = WINBOND_NUVOTON_HARDWARE_MONITOR_LDN; break; } break; case 0xB3: switch (revision & 0xF0) { case 0x50: chip = Chip.W83667HGB; - logicalDeviceNumber = WINBOND_HARDWARE_MONITOR_LDN; + logicalDeviceNumber = WINBOND_NUVOTON_HARDWARE_MONITOR_LDN; + break; + } break; + case 0xB4: + switch (revision & 0xF0) { + case 0x70: + chip = Chip.NCT6771F; + logicalDeviceNumber = WINBOND_NUVOTON_HARDWARE_MONITOR_LDN; break; } break; } if (chip == Chip.Unknown) { if (id != 0 && id != 0xff) { - WinbondFintekExit(); + WinbondNuvotonFintekExit(); - ReportUnknownChip("Winbond / Fintek", ((id << 8) | revision)); + ReportUnknownChip("Winbond / Nuvoton / Fintek", + ((id << 8) | revision)); } } else { @@ -229,7 +237,7 @@ ushort vendorID = ReadWord(FINTEK_VENDOR_ID_REGISTER); - WinbondFintekExit(); + WinbondNuvotonFintekExit(); if (address != verify) { report.Append("Chip ID: 0x"); @@ -270,6 +278,9 @@ case Chip.W83687THF: superIOs.Add(new W836XX(chip, revision, address)); break; + case Chip.NCT6771F: + superIOs.Add(new NCT677X(chip, revision, address)); + break; case Chip.F71858: case Chip.F71862: case Chip.F71869: diff -r 99f16e21cdc8 -r f8e72b2efcc0 Hardware/LPC/NCT677X.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Hardware/LPC/NCT677X.cs Sun Nov 21 17:31:25 2010 +0000 @@ -0,0 +1,225 @@ +/* + + Version: MPL 1.1/GPL 2.0/LGPL 2.1 + + The contents of this file are subject to the Mozilla Public License Version + 1.1 (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + for the specific language governing rights and limitations under the License. + + The Original Code is the Open Hardware Monitor code. + + The Initial Developer of the Original Code is + Michael Möller . + Portions created by the Initial Developer are Copyright (C) 2010 + the Initial Developer. All Rights Reserved. + + Contributor(s): + + Alternatively, the contents of this file may be used under the terms of + either the GNU General Public License Version 2 or later (the "GPL"), or + the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + in which case the provisions of the GPL or the LGPL are applicable instead + of those above. If you wish to allow use of your version of this file only + under the terms of either the GPL or the LGPL, and not to allow others to + use your version of this file under the terms of the MPL, indicate your + decision by deleting the provisions above and replace them with the notice + and other provisions required by the GPL or the LGPL. If you do not delete + the provisions above, a recipient may use your version of this file under + the terms of any one of the MPL, the GPL or the LGPL. + +*/ + +using System.Globalization; +using System.Text; + +namespace OpenHardwareMonitor.Hardware.LPC { + internal class NCT677X : ISuperIO { + + private readonly ushort port; + private readonly byte revision; + + private readonly Chip chip; + + private readonly float?[] voltages = new float?[9]; + private readonly float?[] temperatures = new float?[3]; + private readonly float?[] fans = new float?[4]; + + // Hardware Monitor + private const uint ADDRESS_REGISTER_OFFSET = 0x05; + private const uint DATA_REGISTER_OFFSET = 0x06; + private const byte BANK_SELECT_REGISTER = 0x4E; + + private byte ReadByte(ushort address) { + byte bank = (byte)(address >> 8); + byte register = (byte)(address & 0xFF); + Ring0.WriteIoPort(port + ADDRESS_REGISTER_OFFSET, BANK_SELECT_REGISTER); + Ring0.WriteIoPort(port + DATA_REGISTER_OFFSET, bank); + Ring0.WriteIoPort(port + ADDRESS_REGISTER_OFFSET, register); + return Ring0.ReadIoPort(port + DATA_REGISTER_OFFSET); + } + + // Consts + private const ushort NUVOTON_VENDOR_ID = 0x5CA3; + + // Hardware Monitor Registers + private const ushort VENDOR_ID_HIGH_REGISTER = 0x804F; + private const ushort VENDOR_ID_LOW_REGISTER = 0x004F; + private const ushort VOLTAGE_VBAT_REG = 0x0551; + + private readonly ushort[] TEMPERATURE_REG = + { 0x150, 0x250, 0x27, 0x62B, 0x62C, 0x62D }; + private readonly ushort[] TEMPERATURE_HALF_REG = + { 0x151, 0x251, 0, 0x62E, 0x62E, 0x62E }; + private readonly ushort[] TEMPERATURE_SRC_REG = + { 0x621, 0x622, 0x623, 0x624, 0x625, 0x626 }; + private readonly int[] TEMPERATURE_HALF_BIT = { 7, 7, -1, 0, 1, 2 }; + private readonly ushort[] VOLTAGE_REG = + { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x550, 0x551 }; + private readonly ushort[] FAN_RPM_REG = { 0x656, 0x658, 0x65A, 0x65C}; + + private enum TemperatureSource : byte { + SYSTIN = 1, + CPUTIN = 2, + AUXTIN = 3, + SMBUSMASTER = 4, + PECI0 = 5, + PECI1 = 6, + PECI2 = 7, + PECI3 = 8, + PECI4 = 9, + PECI5 = 10, + PECI6 = 11, + PECI7 = 12, + PCH_CHIP_CPU_MAX_TEMP = 13, + PCH_CHIP_TEMP = 14, + PCH_CPU_TEMP = 15, + PCH_MCH_TEMP = 16, + PCH_DIM0_TEMP = 17, + PCH_DIM1_TEMP = 18, + PCH_DIM2_TEMP = 19, + PCH_DIM3_TEMP = 20 + } + + public NCT677X(Chip chip, byte revision, ushort port) { + this.chip = chip; + this.revision = revision; + this.port = port; + + if (!IsNuvotonVendor()) + return; + } + + private bool IsNuvotonVendor() { + return ((ReadByte(VENDOR_ID_HIGH_REGISTER) << 8) | + ReadByte(VENDOR_ID_LOW_REGISTER)) == NUVOTON_VENDOR_ID; + } + + public byte? ReadGPIO(int index) { + return null; + } + + public void WriteGPIO(int index, byte value) { } + + public Chip Chip { get { return chip; } } + public float?[] Voltages { get { return voltages; } } + public float?[] Temperatures { get { return temperatures; } } + public float?[] Fans { get { return fans; } } + + public void Update() { + if (!Ring0.WaitIsaBusMutex(10)) + return; + + for (int i = 0; i < voltages.Length; i++) { + float value = 0.008f * ReadByte(VOLTAGE_REG[i]); + bool valid = value > 0; + + // check if battery voltage monitor is enabled + if (valid && VOLTAGE_REG[i] == VOLTAGE_VBAT_REG) + valid = (ReadByte(0x005D) & 0x01) > 0; + + voltages[i] = valid ? value : (float?)null; + } + + for (int i = 0; i < TEMPERATURE_REG.Length; i++) { + float value = ReadByte(TEMPERATURE_REG[i]); + if (TEMPERATURE_HALF_BIT[i] > 0) { + value += 0.5f * ((ReadByte(TEMPERATURE_HALF_REG[i]) >> + TEMPERATURE_HALF_BIT[i]) & 0x1); + } + + TemperatureSource source = (TemperatureSource) + ReadByte(TEMPERATURE_SRC_REG[i]); + + switch (source) { + case TemperatureSource.CPUTIN: temperatures[0] = value; break; + case TemperatureSource.AUXTIN: temperatures[1] = value; break; + case TemperatureSource.SYSTIN: temperatures[2] = value; break; + } + } + + for (int i = 0; i < fans.Length; i++) { + byte high = ReadByte(FAN_RPM_REG[i]); + byte low = ReadByte((ushort)(FAN_RPM_REG[i] + 1)); + fans[i] = (high << 8) | low; + } + + Ring0.ReleaseIsaBusMutex(); + } + + public string GetReport() { + StringBuilder r = new StringBuilder(); + + r.AppendLine("LPC " + this.GetType().Name); + r.AppendLine(); + r.Append("Chip ID: 0x"); r.AppendLine(chip.ToString("X")); + r.Append("Chip revision: 0x"); + r.AppendLine(revision.ToString("X", CultureInfo.InvariantCulture)); + r.Append("Base Adress: 0x"); + r.AppendLine(port.ToString("X4", CultureInfo.InvariantCulture)); + r.AppendLine(); + + if (!Ring0.WaitIsaBusMutex(100)) + return r.ToString(); + + r.AppendLine("Hardware Monitor Registers"); + r.AppendLine(); + r.AppendLine(" 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F"); + r.AppendLine(); + for (int i = 0; i <= 0x7; i++) { + r.Append(" "); + r.Append((i << 4).ToString("X3", CultureInfo.InvariantCulture)); + r.Append(" "); + for (int j = 0; j <= 0xF; j++) { + r.Append(" "); + r.Append(ReadByte((ushort)((i << 4) | j)).ToString( + "X2", CultureInfo.InvariantCulture)); + } + r.AppendLine(); + } + for (int bank = 1; bank <= 15; bank++) { + for (int i = 0x5; i < 0x6; i++) { + r.Append(" "); + r.Append((i << 4).ToString("X3", CultureInfo.InvariantCulture)); + r.Append(" "); + for (int j = 0; j <= 0xF; j++) { + r.Append(" "); + r.Append(ReadByte((ushort)((bank << 8) | (i << 4) | j)).ToString( + "X2", CultureInfo.InvariantCulture)); + } + r.AppendLine(); + } + } + r.AppendLine(); + + Ring0.ReleaseIsaBusMutex(); + + return r.ToString(); + } + } +} diff -r 99f16e21cdc8 -r f8e72b2efcc0 Hardware/Mainboard/SuperIOHardware.cs --- a/Hardware/Mainboard/SuperIOHardware.cs Sun Nov 21 12:28:31 2010 +0000 +++ b/Hardware/Mainboard/SuperIOHardware.cs Sun Nov 21 17:31:25 2010 +0000 @@ -741,6 +741,24 @@ f.Add(new Fan("CPU Fan", 1)); f.Add(new Fan("Auxiliary Fan", 2)); break; + case Chip.NCT6771F: + v.Add(new Voltage("CPU VCore", 0)); + v.Add(new Voltage("Voltage #2", 1, true)); + v.Add(new Voltage("AVCC", 2, 34, 34)); + v.Add(new Voltage("3VCC", 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)); + t.Add(new Temperature("CPU", 0)); + t.Add(new Temperature("Auxiliary", 1)); + t.Add(new Temperature("System", 2)); + f.Add(new Fan("System Fan", 0)); + f.Add(new Fan("CPU Fan", 1)); + f.Add(new Fan("Auxiliary Fan", 2)); + f.Add(new Fan("Auxiliary Fan #2", 4)); + break; default: for (int i = 0; i < superIO.Voltages.Length; i++) v.Add(new Voltage("Voltage #" + (i + 1), i, true)); diff -r 99f16e21cdc8 -r f8e72b2efcc0 OpenHardwareMonitorLib.csproj --- a/OpenHardwareMonitorLib.csproj Sun Nov 21 12:28:31 2010 +0000 +++ b/OpenHardwareMonitorLib.csproj Sun Nov 21 17:31:25 2010 +0000 @@ -69,6 +69,7 @@ +