1.1 --- a/Hardware/LPC/NCT677X.cs Sun Jun 24 16:16:46 2012 +0000
1.2 +++ b/Hardware/LPC/NCT677X.cs Sun Jul 01 21:44:07 2012 +0000
1.3 @@ -4,10 +4,11 @@
1.4 License, v. 2.0. If a copy of the MPL was not distributed with this
1.5 file, You can obtain one at http://mozilla.org/MPL/2.0/.
1.6
1.7 - Copyright (C) 2010-2011 Michael Möller <mmoeller@openhardwaremonitor.org>
1.8 + Copyright (C) 2010-2012 Michael Möller <mmoeller@openhardwaremonitor.org>
1.9
1.10 */
1.11
1.12 +using System;
1.13 using System.Globalization;
1.14 using System.Text;
1.15
1.16 @@ -19,10 +20,10 @@
1.17
1.18 private readonly Chip chip;
1.19
1.20 - private readonly float?[] voltages = new float?[9];
1.21 - private readonly float?[] temperatures = new float?[4];
1.22 - private readonly float?[] fans = new float?[0];
1.23 - private readonly float?[] controls = new float?[3];
1.24 + private readonly float?[] voltages;
1.25 + private readonly float?[] temperatures;
1.26 + private readonly float?[] fans ;
1.27 + private readonly float?[] controls;
1.28
1.29 // Hardware Monitor
1.30 private const uint ADDRESS_REGISTER_OFFSET = 0x05;
1.31 @@ -52,33 +53,33 @@
1.32
1.33 // Hardware Monitor Registers
1.34 private const ushort VENDOR_ID_HIGH_REGISTER = 0x804F;
1.35 - private const ushort VENDOR_ID_LOW_REGISTER = 0x004F;
1.36 - private const ushort VOLTAGE_VBAT_REG = 0x0551;
1.37 + private const ushort VENDOR_ID_LOW_REGISTER = 0x004F;
1.38 +
1.39 + private readonly ushort[] FAN_PWM_OUT_REG =
1.40 + { 0x001, 0x003, 0x011, 0x013, 0x015 };
1.41 + private readonly ushort[] FAN_PWM_COMMAND_REG =
1.42 + { 0x109, 0x209, 0x309, 0x809, 0x909 };
1.43 + private readonly ushort[] FAN_CONTROL_MODE_REG =
1.44 + { 0x102, 0x202, 0x302, 0x802, 0x902 };
1.45
1.46 - private readonly ushort[] TEMPERATURE_REG =
1.47 - { 0x027, 0x73, 0x75, 0x77, 0x150, 0x250, 0x62B, 0x62C, 0x62D };
1.48 - private readonly ushort[] TEMPERATURE_HALF_REG =
1.49 - { 0, 0x74, 0x76, 0x78, 0x151, 0x251, 0x62E, 0x62E, 0x62E };
1.50 - private readonly ushort[] TEMPERATURE_SRC_REG =
1.51 - { 0x621, 0x100, 0x200, 0x300, 0x622, 0x623, 0x624, 0x625, 0x626 };
1.52 - private readonly int[] TEMPERATURE_HALF_BIT =
1.53 - { -1, 7, 7, 7, 7, 7, 0, 1, 2 };
1.54 - private readonly ushort[] VOLTAGE_REG =
1.55 - { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x550, 0x551 };
1.56 - private readonly ushort[] FAN_RPM_REG =
1.57 - { 0x656, 0x658, 0x65A, 0x65C, 0x65E};
1.58 - private readonly ushort[] FAN_PWM_OUT_REG =
1.59 - { 0x001, 0x003, 0x011 };
1.60 - private readonly ushort[] FAN_PWM_COMMAND_REG =
1.61 - { 0x109, 0x209, 0x309 };
1.62 - private readonly ushort[] FAN_CONTROL_MODE_REG =
1.63 - { 0x102, 0x202, 0x302 };
1.64 -
1.65 + private readonly ushort fanRpmBaseRegister;
1.66 private readonly int minFanRPM;
1.67
1.68 - private bool[] restoreDefaultFanControlRequired = { false, false, false };
1.69 - private byte[] initialFanControlMode = new byte[3];
1.70 - private byte[] initialFanPwmCommand = new byte[3];
1.71 + private bool[] restoreDefaultFanControlRequired = new bool[5];
1.72 + private byte[] initialFanControlMode = new byte[5];
1.73 + private byte[] initialFanPwmCommand = new byte[5];
1.74 +
1.75 + private readonly ushort[] voltageRegisters;
1.76 + private readonly ushort voltageVBatRegister;
1.77 +
1.78 + private readonly byte[] temperaturesSource;
1.79 +
1.80 + private readonly ushort[] temperatureRegister;
1.81 + private readonly ushort[] temperatureHalfRegister;
1.82 + private readonly int[] temperatureHalfBit;
1.83 + private readonly ushort[] temperatureSourceRegister;
1.84 +
1.85 + private readonly ushort?[] alternateTemperatureRegister;
1.86
1.87 private enum SourceNCT6771F : byte {
1.88 SYSTIN = 1,
1.89 @@ -128,6 +129,34 @@
1.90 BYTE_TEMP = 22
1.91 }
1.92
1.93 + private enum SourceNCT6779D : byte {
1.94 + SYSTIN = 1,
1.95 + CPUTIN = 2,
1.96 + AUXTIN0 = 3,
1.97 + AUXTIN1 = 4,
1.98 + AUXTIN2 = 5,
1.99 + AUXTIN3 = 6,
1.100 + SMBUSMASTER_0 = 8,
1.101 + SMBUSMASTER_1 = 9,
1.102 + SMBUSMASTER_2 = 10,
1.103 + SMBUSMASTER_3 = 11,
1.104 + SMBUSMASTER_4 = 12,
1.105 + SMBUSMASTER_5 = 13,
1.106 + SMBUSMASTER_6 = 14,
1.107 + SMBUSMASTER_7 = 15,
1.108 + PECI_0 = 16,
1.109 + PECI_1 = 17,
1.110 + PCH_CHIP_CPU_MAX_TEMP = 18,
1.111 + PCH_CHIP_TEMP = 19,
1.112 + PCH_CPU_TEMP = 20,
1.113 + PCH_MCH_TEMP = 21,
1.114 + PCH_DIM0_TEMP = 22,
1.115 + PCH_DIM1_TEMP = 23,
1.116 + PCH_DIM2_TEMP = 24,
1.117 + PCH_DIM3_TEMP = 25,
1.118 + BYTE_TEMP = 26
1.119 + }
1.120 +
1.121 public NCT677X(Chip chip, byte revision, ushort port) {
1.122 this.chip = chip;
1.123 this.revision = revision;
1.124 @@ -137,15 +166,93 @@
1.125 return;
1.126
1.127 switch (chip) {
1.128 - case LPC.Chip.NCT6771F:
1.129 - fans = new float?[4];
1.130 - // min value RPM value with 16-bit fan counter
1.131 - minFanRPM = (int)(1.35e6 / 0xFFFF);
1.132 + case Chip.NCT6771F:
1.133 + case Chip.NCT6776F:
1.134 + if (chip == Chip.NCT6771F) {
1.135 + fans = new float?[4];
1.136 +
1.137 + // min value RPM value with 16-bit fan counter
1.138 + minFanRPM = (int)(1.35e6 / 0xFFFF);
1.139 +
1.140 + temperaturesSource = new byte[] {
1.141 + (byte)SourceNCT6771F.PECI_0,
1.142 + (byte)SourceNCT6771F.CPUTIN,
1.143 + (byte)SourceNCT6771F.AUXTIN,
1.144 + (byte)SourceNCT6771F.SYSTIN
1.145 + };
1.146 + } else {
1.147 + fans = new float?[5];
1.148 +
1.149 + // min value RPM value with 13-bit fan counter
1.150 + minFanRPM = (int)(1.35e6 / 0x1FFF);
1.151 +
1.152 + temperaturesSource = new byte[] {
1.153 + (byte)SourceNCT6776F.PECI_0,
1.154 + (byte)SourceNCT6776F.CPUTIN,
1.155 + (byte)SourceNCT6776F.AUXTIN,
1.156 + (byte)SourceNCT6776F.SYSTIN
1.157 + };
1.158 + }
1.159 + fanRpmBaseRegister = 0x656;
1.160 +
1.161 + controls = new float?[3];
1.162 +
1.163 + voltages = new float?[9];
1.164 + voltageRegisters = new ushort[]
1.165 + { 0x020, 0x021, 0x022, 0x023, 0x024, 0x025, 0x026, 0x550, 0x551 };
1.166 + voltageVBatRegister = 0x551;
1.167 +
1.168 + temperatures = new float?[4];
1.169 + temperatureRegister = new ushort[]
1.170 + { 0x027, 0x073, 0x075, 0x077, 0x150, 0x250, 0x62B, 0x62C, 0x62D };
1.171 + temperatureHalfRegister = new ushort[]
1.172 + { 0, 0x074, 0x076, 0x078, 0x151, 0x251, 0x62E, 0x62E, 0x62E };
1.173 + temperatureHalfBit = new int[]
1.174 + { -1, 7, 7, 7, 7, 7, 0, 1, 2 };
1.175 + temperatureSourceRegister = new ushort[]
1.176 + { 0x621, 0x100, 0x200, 0x300, 0x622, 0x623, 0x624, 0x625, 0x626 };
1.177 +
1.178 + alternateTemperatureRegister = new ushort?[]
1.179 + { null, null, null, null };
1.180 break;
1.181 - case LPC.Chip.NCT6776F:
1.182 + case Chip.NCT6779D:
1.183 fans = new float?[5];
1.184 + fanRpmBaseRegister = 0x4C0;
1.185 +
1.186 // min value RPM value with 13-bit fan counter
1.187 minFanRPM = (int)(1.35e6 / 0x1FFF);
1.188 +
1.189 + controls = new float?[5];
1.190 +
1.191 + voltages = new float?[15];
1.192 + voltageRegisters = new ushort[]
1.193 + { 0x480, 0x481, 0x482, 0x483, 0x484, 0x485, 0x486, 0x487, 0x488,
1.194 + 0x489, 0x48A, 0x48B, 0x48C, 0x48D, 0x48E };
1.195 + voltageVBatRegister = 0x488;
1.196 +
1.197 + temperatures = new float?[7];
1.198 + temperaturesSource = new byte[] {
1.199 + (byte)SourceNCT6779D.PECI_0,
1.200 + (byte)SourceNCT6779D.CPUTIN,
1.201 + (byte)SourceNCT6779D.SYSTIN,
1.202 + (byte)SourceNCT6779D.AUXTIN0,
1.203 + (byte)SourceNCT6779D.AUXTIN1,
1.204 + (byte)SourceNCT6779D.AUXTIN2,
1.205 + (byte)SourceNCT6779D.AUXTIN3
1.206 + };
1.207 +
1.208 + temperatureRegister = new ushort[]
1.209 + { 0x027, 0x073, 0x075, 0x077, 0x079, 0x07B, 0x150 };
1.210 + temperatureHalfRegister = new ushort[]
1.211 + { 0, 0x074, 0x076, 0x078, 0x07A, 0x07C, 0x151 };
1.212 + temperatureHalfBit = new int[]
1.213 + { -1, 7, 7, 7, 7, 7, 7 };
1.214 + temperatureSourceRegister = new ushort[]
1.215 + { 0x621, 0x100, 0x200, 0x300, 0x800, 0x900, 0x622 };
1.216 +
1.217 + alternateTemperatureRegister = new ushort?[]
1.218 + {null, 0x491, 0x490, 0x492, 0x493, 0x494, 0x495 };
1.219 +
1.220 break;
1.221 }
1.222 }
1.223 @@ -179,6 +286,9 @@
1.224 }
1.225
1.226 public void SetControl(int index, byte? value) {
1.227 + if (index < 0 || index >= controls.Length)
1.228 + throw new ArgumentOutOfRangeException("index");
1.229 +
1.230 if (!Ring0.WaitIsaBusMutex(10))
1.231 return;
1.232
1.233 @@ -208,51 +318,48 @@
1.234 return;
1.235
1.236 for (int i = 0; i < voltages.Length; i++) {
1.237 - float value = 0.008f * ReadByte(VOLTAGE_REG[i]);
1.238 + float value = 0.008f * ReadByte(voltageRegisters[i]);
1.239 bool valid = value > 0;
1.240
1.241 // check if battery voltage monitor is enabled
1.242 - if (valid && VOLTAGE_REG[i] == VOLTAGE_VBAT_REG)
1.243 + if (valid && voltageRegisters[i] == voltageVBatRegister)
1.244 valid = (ReadByte(0x005D) & 0x01) > 0;
1.245
1.246 voltages[i] = valid ? value : (float?)null;
1.247 }
1.248
1.249 - for (int i = TEMPERATURE_REG.Length - 1; i >= 0 ; i--) {
1.250 - int value = ((sbyte)ReadByte(TEMPERATURE_REG[i])) << 1;
1.251 - if (TEMPERATURE_HALF_BIT[i] > 0) {
1.252 - value |= ((ReadByte(TEMPERATURE_HALF_REG[i]) >>
1.253 - TEMPERATURE_HALF_BIT[i]) & 0x1);
1.254 + int temperatureSourceMask = 0;
1.255 + for (int i = temperatureRegister.Length - 1; i >= 0 ; i--) {
1.256 + int value = ((sbyte)ReadByte(temperatureRegister[i])) << 1;
1.257 + if (temperatureHalfBit[i] > 0) {
1.258 + value |= ((ReadByte(temperatureHalfRegister[i]) >>
1.259 + temperatureHalfBit[i]) & 0x1);
1.260 }
1.261
1.262 - byte source = ReadByte(TEMPERATURE_SRC_REG[i]);
1.263 + byte source = ReadByte(temperatureSourceRegister[i]);
1.264 + temperatureSourceMask |= 1 << source;
1.265
1.266 float? temperature = 0.5f * value;
1.267 if (temperature > 125 || temperature < -55)
1.268 temperature = null;
1.269
1.270 - switch (chip) {
1.271 - case Chip.NCT6771F:
1.272 - switch ((SourceNCT6771F)source) {
1.273 - case SourceNCT6771F.PECI_0: temperatures[0] = temperature; break;
1.274 - case SourceNCT6771F.CPUTIN: temperatures[1] = temperature; break;
1.275 - case SourceNCT6771F.AUXTIN: temperatures[2] = temperature; break;
1.276 - case SourceNCT6771F.SYSTIN: temperatures[3] = temperature; break;
1.277 -
1.278 - } break;
1.279 - case Chip.NCT6776F:
1.280 - switch ((SourceNCT6776F)source) {
1.281 - case SourceNCT6776F.PECI_0: temperatures[0] = temperature; break;
1.282 - case SourceNCT6776F.CPUTIN: temperatures[1] = temperature; break;
1.283 - case SourceNCT6776F.AUXTIN: temperatures[2] = temperature; break;
1.284 - case SourceNCT6776F.SYSTIN: temperatures[3] = temperature; break;
1.285 - } break;
1.286 - }
1.287 + for (int j = 0; j < temperatures.Length; j++)
1.288 + if (temperaturesSource[j] == source)
1.289 + temperatures[j] = temperature;
1.290 + }
1.291 + for (int i = 0; i < alternateTemperatureRegister.Length; i++) {
1.292 + if (!alternateTemperatureRegister[i].HasValue)
1.293 + continue;
1.294 +
1.295 + if ((temperatureSourceMask & (1 << temperaturesSource[i])) > 0)
1.296 + continue;
1.297 +
1.298 + temperatures[i] = ReadByte(alternateTemperatureRegister[i].Value);
1.299 }
1.300
1.301 for (int i = 0; i < fans.Length; i++) {
1.302 - byte high = ReadByte(FAN_RPM_REG[i]);
1.303 - byte low = ReadByte((ushort)(FAN_RPM_REG[i] + 1));
1.304 + byte high = ReadByte((ushort)(fanRpmBaseRegister + (i << 1)));
1.305 + byte low = ReadByte((ushort)(fanRpmBaseRegister + (i << 1) + 1));
1.306 int value = (high << 8) | low;
1.307
1.308 fans[i] = value > minFanRPM ? value : 0;
1.309 @@ -286,9 +393,11 @@
1.310 0x100, 0x110, 0x120, 0x130, 0x140, 0x150,
1.311 0x200, 0x220, 0x230, 0x240, 0x250,
1.312 0x300, 0x320, 0x330, 0x340,
1.313 - 0x400, 0x410, 0x420, 0x440, 0x450, 0x460,
1.314 + 0x400, 0x410, 0x420, 0x440, 0x450, 0x460, 0x480, 0x490, 0x4C0,
1.315 0x500, 0x550,
1.316 0x600, 0x610 ,0x620, 0x630, 0x640, 0x650, 0x660, 0x670,
1.317 + 0x800,
1.318 + 0x900,
1.319 0xA00, 0xA10, 0xA20, 0xA30, 0xA50, 0xA60, 0xA70,
1.320 0xB00, 0xB10, 0xB20, 0xB30, 0xB50, 0xB60, 0xB70,
1.321 0xC00, 0xC10, 0xC20, 0xC30, 0xC50, 0xC60, 0xC70,