Added first experimental support for the Nuvoton NCT6771F super I/O chip.
authormoel.mich
Sun, 21 Nov 2010 17:31:25 +0000
changeset 245f8e72b2efcc0
parent 244 99f16e21cdc8
child 246 59024371cd50
Added first experimental support for the Nuvoton NCT6771F super I/O chip.
Hardware/LPC/Chip.cs
Hardware/LPC/LPCIO.cs
Hardware/LPC/NCT677X.cs
Hardware/Mainboard/SuperIOHardware.cs
OpenHardwareMonitorLib.csproj
     1.1 --- a/Hardware/LPC/Chip.cs	Sun Nov 21 12:28:31 2010 +0000
     1.2 +++ b/Hardware/LPC/Chip.cs	Sun Nov 21 17:31:25 2010 +0000
     1.3 @@ -53,12 +53,13 @@
     1.4      W83667HG = 0xA510,
     1.5      W83667HGB = 0xB350,
     1.6      W83687THF = 0x8541,
     1.7 +    NCT6771F = 0xB470,
     1.8      F71858 = 0x0507,
     1.9      F71862 = 0x0601, 
    1.10      F71869 = 0x0814,
    1.11      F71882 = 0x0541,
    1.12      F71889ED = 0x0909,
    1.13 -    F71889F = 0x0723      
    1.14 +    F71889F = 0x0723     
    1.15    }
    1.16  
    1.17    internal class ChipName {
    1.18 @@ -87,6 +88,7 @@
    1.19          case Chip.W83667HG: return "Winbond W83667HG";
    1.20          case Chip.W83667HGB: return "Winbond W83667HG-B";
    1.21          case Chip.W83687THF: return "Winbond W83687THF";
    1.22 +        case Chip.NCT6771F: return "Nuvoton NCT6771F";
    1.23          case Chip.Unknown: return "Unkown";
    1.24          default: return "Unknown";
    1.25        }
     2.1 --- a/Hardware/LPC/LPCIO.cs	Sun Nov 21 12:28:31 2010 +0000
     2.2 +++ b/Hardware/LPC/LPCIO.cs	Sun Nov 21 17:31:25 2010 +0000
     2.3 @@ -88,27 +88,27 @@
     2.4        report.AppendLine();
     2.5      }
     2.6  
     2.7 -    #region Winbond, Fintek
     2.8 +    #region Winbond, Nuvoton, Fintek
     2.9  
    2.10      private const byte FINTEK_VENDOR_ID_REGISTER = 0x23;
    2.11      private const ushort FINTEK_VENDOR_ID = 0x1934;
    2.12  
    2.13 -    private const byte WINBOND_HARDWARE_MONITOR_LDN = 0x0B;
    2.14 +    private const byte WINBOND_NUVOTON_HARDWARE_MONITOR_LDN = 0x0B;
    2.15  
    2.16      private const byte F71858_HARDWARE_MONITOR_LDN = 0x02;
    2.17      private const byte FINTEK_HARDWARE_MONITOR_LDN = 0x04;
    2.18  
    2.19 -    private void WinbondFintekEnter() {
    2.20 +    private void WinbondNuvotonFintekEnter() {
    2.21        Ring0.WriteIoPort(registerPort, 0x87);
    2.22        Ring0.WriteIoPort(registerPort, 0x87);
    2.23      }
    2.24  
    2.25 -    private void WinbondFintekExit() {
    2.26 +    private void WinbondNuvotonFintekExit() {
    2.27        Ring0.WriteIoPort(registerPort, 0xAA);
    2.28      }
    2.29  
    2.30      private bool DetectWinbondFintek() {
    2.31 -      WinbondFintekEnter();
    2.32 +      WinbondNuvotonFintekEnter();
    2.33  
    2.34        byte logicalDeviceNumber = 0;
    2.35        byte id = ReadByte(CHIP_ID_REGISTER);
    2.36 @@ -160,21 +160,21 @@
    2.37              case 0x3A:
    2.38              case 0x41:
    2.39                chip = Chip.W83627HF;
    2.40 -              logicalDeviceNumber = WINBOND_HARDWARE_MONITOR_LDN;
    2.41 +              logicalDeviceNumber = WINBOND_NUVOTON_HARDWARE_MONITOR_LDN;
    2.42                break;
    2.43            } break;
    2.44          case 0x82:
    2.45            switch (revision & 0xF0) {
    2.46              case 0x80:
    2.47                chip = Chip.W83627THF;
    2.48 -              logicalDeviceNumber = WINBOND_HARDWARE_MONITOR_LDN;
    2.49 +              logicalDeviceNumber = WINBOND_NUVOTON_HARDWARE_MONITOR_LDN;
    2.50                break;
    2.51            } break;
    2.52          case 0x85:
    2.53            switch (revision) {
    2.54              case 0x41:
    2.55                chip = Chip.W83687THF;
    2.56 -              logicalDeviceNumber = WINBOND_HARDWARE_MONITOR_LDN;
    2.57 +              logicalDeviceNumber = WINBOND_NUVOTON_HARDWARE_MONITOR_LDN;
    2.58                break;
    2.59            } break;
    2.60          case 0x88:
    2.61 @@ -182,43 +182,51 @@
    2.62              case 0x50:
    2.63              case 0x60:
    2.64                chip = Chip.W83627EHF;
    2.65 -              logicalDeviceNumber = WINBOND_HARDWARE_MONITOR_LDN;
    2.66 +              logicalDeviceNumber = WINBOND_NUVOTON_HARDWARE_MONITOR_LDN;
    2.67                break;
    2.68            } break;
    2.69          case 0xA0:
    2.70            switch (revision & 0xF0) {
    2.71              case 0x20:
    2.72                chip = Chip.W83627DHG;
    2.73 -              logicalDeviceNumber = WINBOND_HARDWARE_MONITOR_LDN;
    2.74 +              logicalDeviceNumber = WINBOND_NUVOTON_HARDWARE_MONITOR_LDN;
    2.75                break;
    2.76            } break;
    2.77          case 0xA5:
    2.78            switch (revision & 0xF0) {
    2.79              case 0x10:
    2.80                chip = Chip.W83667HG;
    2.81 -              logicalDeviceNumber = WINBOND_HARDWARE_MONITOR_LDN;
    2.82 +              logicalDeviceNumber = WINBOND_NUVOTON_HARDWARE_MONITOR_LDN;
    2.83                break;
    2.84            } break;
    2.85          case 0xB0:
    2.86            switch (revision & 0xF0) {
    2.87              case 0x70:
    2.88                chip = Chip.W83627DHGP;
    2.89 -              logicalDeviceNumber = WINBOND_HARDWARE_MONITOR_LDN;
    2.90 +              logicalDeviceNumber = WINBOND_NUVOTON_HARDWARE_MONITOR_LDN;
    2.91                break;
    2.92            } break;
    2.93          case 0xB3:
    2.94            switch (revision & 0xF0) {
    2.95              case 0x50:
    2.96                chip = Chip.W83667HGB;
    2.97 -              logicalDeviceNumber = WINBOND_HARDWARE_MONITOR_LDN;
    2.98 +              logicalDeviceNumber = WINBOND_NUVOTON_HARDWARE_MONITOR_LDN;
    2.99 +              break;
   2.100 +          } break;
   2.101 +        case 0xB4:
   2.102 +          switch (revision & 0xF0) {
   2.103 +            case 0x70:
   2.104 +              chip = Chip.NCT6771F;
   2.105 +              logicalDeviceNumber = WINBOND_NUVOTON_HARDWARE_MONITOR_LDN;
   2.106                break;
   2.107            } break;
   2.108        }
   2.109        if (chip == Chip.Unknown) {
   2.110          if (id != 0 && id != 0xff) {
   2.111 -          WinbondFintekExit();
   2.112 +          WinbondNuvotonFintekExit();
   2.113  
   2.114 -          ReportUnknownChip("Winbond / Fintek", ((id << 8) | revision));
   2.115 +          ReportUnknownChip("Winbond / Nuvoton / Fintek", 
   2.116 +            ((id << 8) | revision));
   2.117          }
   2.118        } else {
   2.119  
   2.120 @@ -229,7 +237,7 @@
   2.121  
   2.122          ushort vendorID = ReadWord(FINTEK_VENDOR_ID_REGISTER);
   2.123  
   2.124 -        WinbondFintekExit();
   2.125 +        WinbondNuvotonFintekExit();
   2.126  
   2.127          if (address != verify) {
   2.128            report.Append("Chip ID: 0x");
   2.129 @@ -270,6 +278,9 @@
   2.130            case Chip.W83687THF:
   2.131              superIOs.Add(new W836XX(chip, revision, address));
   2.132              break;
   2.133 +          case Chip.NCT6771F:
   2.134 +            superIOs.Add(new NCT677X(chip, revision, address));
   2.135 +            break;
   2.136            case Chip.F71858:
   2.137            case Chip.F71862:
   2.138            case Chip.F71869:
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/Hardware/LPC/NCT677X.cs	Sun Nov 21 17:31:25 2010 +0000
     3.3 @@ -0,0 +1,225 @@
     3.4 +/*
     3.5 +  
     3.6 +  Version: MPL 1.1/GPL 2.0/LGPL 2.1
     3.7 +
     3.8 +  The contents of this file are subject to the Mozilla Public License Version
     3.9 +  1.1 (the "License"); you may not use this file except in compliance with
    3.10 +  the License. You may obtain a copy of the License at
    3.11 + 
    3.12 +  http://www.mozilla.org/MPL/
    3.13 +
    3.14 +  Software distributed under the License is distributed on an "AS IS" basis,
    3.15 +  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
    3.16 +  for the specific language governing rights and limitations under the License.
    3.17 +
    3.18 +  The Original Code is the Open Hardware Monitor code.
    3.19 +
    3.20 +  The Initial Developer of the Original Code is 
    3.21 +  Michael Möller <m.moeller@gmx.ch>.
    3.22 +  Portions created by the Initial Developer are Copyright (C) 2010
    3.23 +  the Initial Developer. All Rights Reserved.
    3.24 +
    3.25 +  Contributor(s):
    3.26 +
    3.27 +  Alternatively, the contents of this file may be used under the terms of
    3.28 +  either the GNU General Public License Version 2 or later (the "GPL"), or
    3.29 +  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
    3.30 +  in which case the provisions of the GPL or the LGPL are applicable instead
    3.31 +  of those above. If you wish to allow use of your version of this file only
    3.32 +  under the terms of either the GPL or the LGPL, and not to allow others to
    3.33 +  use your version of this file under the terms of the MPL, indicate your
    3.34 +  decision by deleting the provisions above and replace them with the notice
    3.35 +  and other provisions required by the GPL or the LGPL. If you do not delete
    3.36 +  the provisions above, a recipient may use your version of this file under
    3.37 +  the terms of any one of the MPL, the GPL or the LGPL.
    3.38 + 
    3.39 +*/
    3.40 +
    3.41 +using System.Globalization;
    3.42 +using System.Text;
    3.43 +
    3.44 +namespace OpenHardwareMonitor.Hardware.LPC {
    3.45 +  internal class NCT677X : ISuperIO {
    3.46 +
    3.47 +    private readonly ushort port;
    3.48 +    private readonly byte revision;
    3.49 +
    3.50 +    private readonly Chip chip;
    3.51 +
    3.52 +    private readonly float?[] voltages = new float?[9];
    3.53 +    private readonly float?[] temperatures = new float?[3];
    3.54 +    private readonly float?[] fans = new float?[4];
    3.55 +
    3.56 +    // Hardware Monitor
    3.57 +    private const uint ADDRESS_REGISTER_OFFSET = 0x05;
    3.58 +    private const uint DATA_REGISTER_OFFSET = 0x06;
    3.59 +    private const byte BANK_SELECT_REGISTER = 0x4E;
    3.60 +
    3.61 +    private byte ReadByte(ushort address) {
    3.62 +      byte bank = (byte)(address >> 8);
    3.63 +      byte register = (byte)(address & 0xFF);
    3.64 +      Ring0.WriteIoPort(port + ADDRESS_REGISTER_OFFSET, BANK_SELECT_REGISTER);
    3.65 +      Ring0.WriteIoPort(port + DATA_REGISTER_OFFSET, bank);
    3.66 +      Ring0.WriteIoPort(port + ADDRESS_REGISTER_OFFSET, register);
    3.67 +      return Ring0.ReadIoPort(port + DATA_REGISTER_OFFSET);
    3.68 +    }
    3.69 +
    3.70 +    // Consts 
    3.71 +    private const ushort NUVOTON_VENDOR_ID = 0x5CA3;
    3.72 +
    3.73 +    // Hardware Monitor Registers    
    3.74 +    private const ushort VENDOR_ID_HIGH_REGISTER = 0x804F;
    3.75 +    private const ushort VENDOR_ID_LOW_REGISTER = 0x004F;
    3.76 +    private const ushort VOLTAGE_VBAT_REG = 0x0551;
    3.77 +
    3.78 +    private readonly ushort[] TEMPERATURE_REG = 
    3.79 +      { 0x150, 0x250, 0x27, 0x62B, 0x62C, 0x62D };
    3.80 +    private readonly ushort[] TEMPERATURE_HALF_REG = 
    3.81 +      { 0x151, 0x251, 0, 0x62E, 0x62E, 0x62E };    
    3.82 +    private readonly ushort[] TEMPERATURE_SRC_REG = 
    3.83 +      { 0x621, 0x622, 0x623, 0x624, 0x625, 0x626 };
    3.84 +    private readonly int[] TEMPERATURE_HALF_BIT = { 7, 7, -1, 0, 1, 2 };
    3.85 +    private readonly ushort[] VOLTAGE_REG = 
    3.86 +      { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x550, 0x551 };
    3.87 +    private readonly ushort[] FAN_RPM_REG = { 0x656, 0x658, 0x65A, 0x65C};
    3.88 +
    3.89 +    private enum TemperatureSource : byte {
    3.90 +      SYSTIN = 1,
    3.91 +      CPUTIN = 2,
    3.92 +      AUXTIN = 3,
    3.93 +      SMBUSMASTER = 4,
    3.94 +      PECI0 = 5, 
    3.95 +      PECI1 = 6, 
    3.96 +      PECI2 = 7,
    3.97 +      PECI3 = 8,
    3.98 +      PECI4 = 9,
    3.99 +      PECI5 = 10,
   3.100 +      PECI6 = 11,
   3.101 +      PECI7 = 12,
   3.102 +      PCH_CHIP_CPU_MAX_TEMP = 13,
   3.103 +      PCH_CHIP_TEMP = 14,
   3.104 +      PCH_CPU_TEMP = 15,
   3.105 +      PCH_MCH_TEMP = 16, 
   3.106 +      PCH_DIM0_TEMP = 17,
   3.107 +      PCH_DIM1_TEMP = 18,
   3.108 +      PCH_DIM2_TEMP = 19,
   3.109 +      PCH_DIM3_TEMP = 20
   3.110 +    }
   3.111 +
   3.112 +    public NCT677X(Chip chip, byte revision, ushort port) {
   3.113 +      this.chip = chip;
   3.114 +      this.revision = revision;
   3.115 +      this.port = port;
   3.116 +
   3.117 +      if (!IsNuvotonVendor())
   3.118 +        return;      
   3.119 +    }
   3.120 +
   3.121 +    private bool IsNuvotonVendor() {
   3.122 +      return ((ReadByte(VENDOR_ID_HIGH_REGISTER) << 8) |
   3.123 +        ReadByte(VENDOR_ID_LOW_REGISTER)) == NUVOTON_VENDOR_ID;
   3.124 +    }
   3.125 +
   3.126 +    public byte? ReadGPIO(int index) {
   3.127 +      return null;
   3.128 +    }
   3.129 +
   3.130 +    public void WriteGPIO(int index, byte value) { }
   3.131 +
   3.132 +    public Chip Chip { get { return chip; } }
   3.133 +    public float?[] Voltages { get { return voltages; } }
   3.134 +    public float?[] Temperatures { get { return temperatures; } }
   3.135 +    public float?[] Fans { get { return fans; } }
   3.136 +
   3.137 +    public void Update() {
   3.138 +      if (!Ring0.WaitIsaBusMutex(10))
   3.139 +        return;
   3.140 +
   3.141 +      for (int i = 0; i < voltages.Length; i++) {
   3.142 +        float value = 0.008f * ReadByte(VOLTAGE_REG[i]);
   3.143 +        bool valid = value > 0;
   3.144 +
   3.145 +        // check if battery voltage monitor is enabled
   3.146 +        if (valid && VOLTAGE_REG[i] == VOLTAGE_VBAT_REG) 
   3.147 +          valid = (ReadByte(0x005D) & 0x01) > 0;
   3.148 +
   3.149 +        voltages[i] = valid ? value : (float?)null;
   3.150 +      }
   3.151 +
   3.152 +      for (int i = 0; i < TEMPERATURE_REG.Length; i++) {
   3.153 +        float value = ReadByte(TEMPERATURE_REG[i]);
   3.154 +        if (TEMPERATURE_HALF_BIT[i] > 0) {
   3.155 +          value += 0.5f * ((ReadByte(TEMPERATURE_HALF_REG[i]) >> 
   3.156 +            TEMPERATURE_HALF_BIT[i]) & 0x1);
   3.157 +        }
   3.158 +
   3.159 +        TemperatureSource source = (TemperatureSource)
   3.160 +          ReadByte(TEMPERATURE_SRC_REG[i]);
   3.161 +
   3.162 +        switch (source) {
   3.163 +          case TemperatureSource.CPUTIN: temperatures[0] = value; break;
   3.164 +          case TemperatureSource.AUXTIN: temperatures[1] = value; break;
   3.165 +          case TemperatureSource.SYSTIN: temperatures[2] = value; break;
   3.166 +        }
   3.167 +      }
   3.168 +
   3.169 +      for (int i = 0; i < fans.Length; i++) {
   3.170 +        byte high = ReadByte(FAN_RPM_REG[i]);
   3.171 +        byte low = ReadByte((ushort)(FAN_RPM_REG[i] + 1));
   3.172 +        fans[i] = (high << 8) | low;
   3.173 +      }
   3.174 +
   3.175 +      Ring0.ReleaseIsaBusMutex();
   3.176 +    }
   3.177 +
   3.178 +    public string GetReport() {
   3.179 +      StringBuilder r = new StringBuilder();
   3.180 +
   3.181 +      r.AppendLine("LPC " + this.GetType().Name);
   3.182 +      r.AppendLine();
   3.183 +      r.Append("Chip ID: 0x"); r.AppendLine(chip.ToString("X"));
   3.184 +      r.Append("Chip revision: 0x");
   3.185 +      r.AppendLine(revision.ToString("X", CultureInfo.InvariantCulture));
   3.186 +      r.Append("Base Adress: 0x");
   3.187 +      r.AppendLine(port.ToString("X4", CultureInfo.InvariantCulture));
   3.188 +      r.AppendLine();
   3.189 +
   3.190 +      if (!Ring0.WaitIsaBusMutex(100))
   3.191 +        return r.ToString();
   3.192 +
   3.193 +      r.AppendLine("Hardware Monitor Registers");
   3.194 +      r.AppendLine();
   3.195 +      r.AppendLine("       00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F");
   3.196 +      r.AppendLine();
   3.197 +      for (int i = 0; i <= 0x7; i++) {
   3.198 +        r.Append(" ");
   3.199 +        r.Append((i << 4).ToString("X3", CultureInfo.InvariantCulture));
   3.200 +        r.Append("  ");
   3.201 +        for (int j = 0; j <= 0xF; j++) {
   3.202 +          r.Append(" ");
   3.203 +          r.Append(ReadByte((ushort)((i << 4) | j)).ToString(
   3.204 +            "X2", CultureInfo.InvariantCulture));
   3.205 +        }
   3.206 +        r.AppendLine();
   3.207 +      }
   3.208 +      for (int bank = 1; bank <= 15; bank++) {
   3.209 +        for (int i = 0x5; i < 0x6; i++) {
   3.210 +          r.Append(" ");
   3.211 +          r.Append((i << 4).ToString("X3", CultureInfo.InvariantCulture));
   3.212 +          r.Append("  ");
   3.213 +          for (int j = 0; j <= 0xF; j++) {
   3.214 +            r.Append(" ");
   3.215 +            r.Append(ReadByte((ushort)((bank << 8) | (i << 4) | j)).ToString(
   3.216 +              "X2", CultureInfo.InvariantCulture));
   3.217 +          }
   3.218 +          r.AppendLine();
   3.219 +        }
   3.220 +      }
   3.221 +      r.AppendLine();
   3.222 +
   3.223 +      Ring0.ReleaseIsaBusMutex();
   3.224 +
   3.225 +      return r.ToString();
   3.226 +    }
   3.227 +  }
   3.228 +}
     4.1 --- a/Hardware/Mainboard/SuperIOHardware.cs	Sun Nov 21 12:28:31 2010 +0000
     4.2 +++ b/Hardware/Mainboard/SuperIOHardware.cs	Sun Nov 21 17:31:25 2010 +0000
     4.3 @@ -741,6 +741,24 @@
     4.4            f.Add(new Fan("CPU Fan", 1));
     4.5            f.Add(new Fan("Auxiliary Fan", 2));
     4.6            break;
     4.7 +        case Chip.NCT6771F:
     4.8 +          v.Add(new Voltage("CPU VCore", 0));
     4.9 +          v.Add(new Voltage("Voltage #2", 1, true));
    4.10 +          v.Add(new Voltage("AVCC", 2, 34, 34));
    4.11 +          v.Add(new Voltage("3VCC", 3, 34, 34));
    4.12 +          v.Add(new Voltage("Voltage #5", 4, true));
    4.13 +          v.Add(new Voltage("Voltage #6", 5, true));
    4.14 +          v.Add(new Voltage("Voltage #7", 6, true));
    4.15 +          v.Add(new Voltage("3VSB", 7, 34, 34));
    4.16 +          v.Add(new Voltage("VBAT", 8, 34, 34));
    4.17 +          t.Add(new Temperature("CPU", 0));
    4.18 +          t.Add(new Temperature("Auxiliary", 1));
    4.19 +          t.Add(new Temperature("System", 2));
    4.20 +          f.Add(new Fan("System Fan", 0));
    4.21 +          f.Add(new Fan("CPU Fan", 1));
    4.22 +          f.Add(new Fan("Auxiliary Fan", 2));
    4.23 +          f.Add(new Fan("Auxiliary Fan #2", 4));
    4.24 +          break;
    4.25          default:
    4.26            for (int i = 0; i < superIO.Voltages.Length; i++)
    4.27              v.Add(new Voltage("Voltage #" + (i + 1), i, true));
     5.1 --- a/OpenHardwareMonitorLib.csproj	Sun Nov 21 12:28:31 2010 +0000
     5.2 +++ b/OpenHardwareMonitorLib.csproj	Sun Nov 21 17:31:25 2010 +0000
     5.3 @@ -69,6 +69,7 @@
     5.4      <Compile Include="Hardware\CPU\CPUID.cs" />
     5.5      <Compile Include="Hardware\CPU\CPULoad.cs" />
     5.6      <Compile Include="Hardware\CPU\IntelCPU.cs" />
     5.7 +    <Compile Include="Hardware\LPC\NCT677X.cs" />
     5.8      <Compile Include="Hardware\Opcode.cs" />
     5.9      <Compile Include="Hardware\Ring0.cs" />
    5.10      <Compile Include="Hardware\KernelDriver.cs" />