Added first experimental support for fan control on the NCT677X super I/O chips.
1.1 --- a/Hardware/LPC/F718XX.cs Mon Aug 29 18:41:06 2011 +0000
1.2 +++ b/Hardware/LPC/F718XX.cs Wed Aug 31 22:48:49 2011 +0000
1.3 @@ -16,7 +16,7 @@
1.4
1.5 The Initial Developer of the Original Code is
1.6 Michael Möller <m.moeller@gmx.ch>.
1.7 - Portions created by the Initial Developer are Copyright (C) 2009-2010
1.8 + Portions created by the Initial Developer are Copyright (C) 2009-2011
1.9 the Initial Developer. All Rights Reserved.
1.10
1.11 Contributor(s):
1.12 @@ -47,6 +47,7 @@
1.13 private readonly float?[] voltages;
1.14 private readonly float?[] temperatures;
1.15 private readonly float?[] fans;
1.16 + private readonly float?[] controls;
1.17
1.18 // Hardware Monitor
1.19 private const byte ADDRESS_REGISTER_OFFSET = 0x05;
1.20 @@ -71,6 +72,8 @@
1.21
1.22 public void WriteGPIO(int index, byte value) { }
1.23
1.24 + public void SetControl(int index, byte? value) { }
1.25 +
1.26 public F718XX(Chip chip, ushort address) {
1.27 this.address = address;
1.28 this.chip = chip;
1.29 @@ -78,12 +81,14 @@
1.30 voltages = new float?[chip == Chip.F71858 ? 3 : 9];
1.31 temperatures = new float?[3];
1.32 fans = new float?[chip == Chip.F71882 || chip == Chip.F71858? 4 : 3];
1.33 + controls = new float?[0];
1.34 }
1.35
1.36 public Chip Chip { get { return chip; } }
1.37 public float?[] Voltages { get { return voltages; } }
1.38 public float?[] Temperatures { get { return temperatures; } }
1.39 public float?[] Fans { get { return fans; } }
1.40 + public float?[] Controls { get { return controls; } }
1.41
1.42 public string GetReport() {
1.43 StringBuilder r = new StringBuilder();
2.1 --- a/Hardware/LPC/ISuperIO.cs Mon Aug 29 18:41:06 2011 +0000
2.2 +++ b/Hardware/LPC/ISuperIO.cs Wed Aug 31 22:48:49 2011 +0000
2.3 @@ -16,7 +16,7 @@
2.4
2.5 The Initial Developer of the Original Code is
2.6 Michael Möller <m.moeller@gmx.ch>.
2.7 - Portions created by the Initial Developer are Copyright (C) 2009-2010
2.8 + Portions created by the Initial Developer are Copyright (C) 2009-2011
2.9 the Initial Developer. All Rights Reserved.
2.10
2.11 Contributor(s):
2.12 @@ -40,14 +40,21 @@
2.13
2.14 Chip Chip { get; }
2.15
2.16 + // get voltage, temperature, fan and control channel values
2.17 float?[] Voltages { get; }
2.18 float?[] Temperatures { get; }
2.19 float?[] Fans { get; }
2.20 + float?[] Controls { get; }
2.21
2.22 + // set control value, null = auto
2.23 + void SetControl(int index, byte? value);
2.24 +
2.25 + // read and write GPIO
2.26 byte? ReadGPIO(int index);
2.27 void WriteGPIO(int index, byte value);
2.28
2.29 string GetReport();
2.30 +
2.31 void Update();
2.32 }
2.33 }
3.1 --- a/Hardware/LPC/IT87XX.cs Mon Aug 29 18:41:06 2011 +0000
3.2 +++ b/Hardware/LPC/IT87XX.cs Wed Aug 31 22:48:49 2011 +0000
3.3 @@ -54,6 +54,7 @@
3.4 private readonly float?[] voltages = new float?[0];
3.5 private readonly float?[] temperatures = new float?[0];
3.6 private readonly float?[] fans = new float?[0];
3.7 + private readonly float?[] controls = new float?[0];
3.8
3.9 private readonly float voltageGain;
3.10 private readonly bool has16bitFanCounter;
3.11 @@ -103,6 +104,8 @@
3.12 Ring0.WriteIoPort((ushort)(gpioAddress + index), value);
3.13 }
3.14
3.15 + public void SetControl(int index, byte? value) { }
3.16 +
3.17 public IT87XX(Chip chip, ushort address, ushort gpioAddress, byte version) {
3.18
3.19 this.address = address;
3.20 @@ -166,6 +169,7 @@
3.21 public float?[] Voltages { get { return voltages; } }
3.22 public float?[] Temperatures { get { return temperatures; } }
3.23 public float?[] Fans { get { return fans; } }
3.24 + public float?[] Controls { get { return controls; } }
3.25
3.26 public string GetReport() {
3.27 StringBuilder r = new StringBuilder();
4.1 --- a/Hardware/LPC/LMSensors.cs Mon Aug 29 18:41:06 2011 +0000
4.2 +++ b/Hardware/LPC/LMSensors.cs Wed Aug 31 22:48:49 2011 +0000
4.3 @@ -116,6 +116,7 @@
4.4 private readonly float?[] voltages;
4.5 private readonly float?[] temperatures;
4.6 private readonly float?[] fans;
4.7 + private readonly float?[] controls;
4.8
4.9 private readonly FileStream[] voltageStreams;
4.10 private readonly FileStream[] temperatureStreams;
4.11 @@ -125,7 +126,7 @@
4.12 public float?[] Voltages { get { return voltages; } }
4.13 public float?[] Temperatures { get { return temperatures; } }
4.14 public float?[] Fans { get { return fans; } }
4.15 -
4.16 + public float?[] Controls { get { return controls; } }
4.17
4.18 public LMChip(Chip chip, string path) {
4.19 this.path = path;
4.20 @@ -151,6 +152,8 @@
4.21 for (int i = 0; i < fanPaths.Length; i++)
4.22 fanStreams[i] = new FileStream(fanPaths[i],
4.23 FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
4.24 +
4.25 + this.controls = new float?[0];
4.26 }
4.27
4.28 public byte? ReadGPIO(int index) {
4.29 @@ -163,6 +166,8 @@
4.30 return null;
4.31 }
4.32
4.33 + public void SetControl(int index, byte? value) { }
4.34 +
4.35 private string ReadFirstLine(Stream stream) {
4.36 StringBuilder sb = new StringBuilder();
4.37 try {
5.1 --- a/Hardware/LPC/NCT677X.cs Mon Aug 29 18:41:06 2011 +0000
5.2 +++ b/Hardware/LPC/NCT677X.cs Wed Aug 31 22:48:49 2011 +0000
5.3 @@ -49,6 +49,7 @@
5.4 private readonly float?[] voltages = new float?[9];
5.5 private readonly float?[] temperatures = new float?[4];
5.6 private readonly float?[] fans = new float?[0];
5.7 + private readonly float?[] controls = new float?[3];
5.8
5.9 // Hardware Monitor
5.10 private const uint ADDRESS_REGISTER_OFFSET = 0x05;
5.11 @@ -62,6 +63,15 @@
5.12 Ring0.WriteIoPort(port + DATA_REGISTER_OFFSET, bank);
5.13 Ring0.WriteIoPort(port + ADDRESS_REGISTER_OFFSET, register);
5.14 return Ring0.ReadIoPort(port + DATA_REGISTER_OFFSET);
5.15 + }
5.16 +
5.17 + private void WriteByte(ushort address, byte value) {
5.18 + byte bank = (byte)(address >> 8);
5.19 + byte register = (byte)(address & 0xFF);
5.20 + Ring0.WriteIoPort(port + ADDRESS_REGISTER_OFFSET, BANK_SELECT_REGISTER);
5.21 + Ring0.WriteIoPort(port + DATA_REGISTER_OFFSET, bank);
5.22 + Ring0.WriteIoPort(port + ADDRESS_REGISTER_OFFSET, register);
5.23 + Ring0.WriteIoPort(port + DATA_REGISTER_OFFSET, value);
5.24 }
5.25
5.26 // Consts
5.27 @@ -84,9 +94,19 @@
5.28 { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x550, 0x551 };
5.29 private readonly ushort[] FAN_RPM_REG =
5.30 { 0x656, 0x658, 0x65A, 0x65C, 0x65E};
5.31 + private readonly ushort[] FAN_PWM_OUT_REG =
5.32 + { 0x001, 0x003, 0x011 };
5.33 + private readonly ushort[] FAN_PWM_COMMAND_REG =
5.34 + { 0x109, 0x209, 0x309 };
5.35 + private readonly ushort[] FAN_CONTROL_MODE_REG =
5.36 + { 0x102, 0x202, 0x302 };
5.37
5.38 private readonly int minFanRPM;
5.39
5.40 + private bool[] restoreDefaultFanControlRequired = { false, false, false };
5.41 + private byte[] initialFanControlMode = new byte[3];
5.42 + private byte[] initialFanPwmCommand = new byte[3];
5.43 +
5.44 private enum SourceNCT6771F : byte {
5.45 SYSTIN = 1,
5.46 CPUTIN = 2,
5.47 @@ -168,10 +188,47 @@
5.48
5.49 public void WriteGPIO(int index, byte value) { }
5.50
5.51 +
5.52 + private void SaveDefaultFanControl(int index) {
5.53 + if (!restoreDefaultFanControlRequired[index]) {
5.54 + initialFanControlMode[index] = ReadByte(FAN_CONTROL_MODE_REG[index]);
5.55 + initialFanPwmCommand[index] = ReadByte(FAN_PWM_COMMAND_REG[index]);
5.56 + restoreDefaultFanControlRequired[index] = true;
5.57 + }
5.58 + }
5.59 +
5.60 + private void RestoreDefaultFanControl(int index) {
5.61 + if (restoreDefaultFanControlRequired[index]) {
5.62 + WriteByte(FAN_CONTROL_MODE_REG[index], initialFanControlMode[index]);
5.63 + WriteByte(FAN_PWM_COMMAND_REG[index], initialFanPwmCommand[index]);
5.64 + restoreDefaultFanControlRequired[index] = false;
5.65 + }
5.66 + }
5.67 +
5.68 + public void SetControl(int index, byte? value) {
5.69 + if (!Ring0.WaitIsaBusMutex(10))
5.70 + return;
5.71 +
5.72 + if (value.HasValue) {
5.73 + SaveDefaultFanControl(index);
5.74 +
5.75 + // set manual mode
5.76 + WriteByte(FAN_CONTROL_MODE_REG[index], 0);
5.77 +
5.78 + // set output value
5.79 + WriteByte(FAN_PWM_COMMAND_REG[index], value.Value);
5.80 + } else {
5.81 + RestoreDefaultFanControl(index);
5.82 + }
5.83 +
5.84 + Ring0.ReleaseIsaBusMutex();
5.85 + }
5.86 +
5.87 public Chip Chip { get { return chip; } }
5.88 public float?[] Voltages { get { return voltages; } }
5.89 public float?[] Temperatures { get { return temperatures; } }
5.90 public float?[] Fans { get { return fans; } }
5.91 + public float?[] Controls { get { return controls; } }
5.92
5.93 public void Update() {
5.94 if (!Ring0.WaitIsaBusMutex(10))
5.95 @@ -228,6 +285,11 @@
5.96 fans[i] = value > minFanRPM ? value : 0;
5.97 }
5.98
5.99 + for (int i = 0; i < controls.Length; i++) {
5.100 + int value = ReadByte(FAN_PWM_OUT_REG[i]);
5.101 + controls[i] = value / 2.55f;
5.102 + }
5.103 +
5.104 Ring0.ReleaseIsaBusMutex();
5.105 }
5.106
6.1 --- a/Hardware/LPC/W836XX.cs Mon Aug 29 18:41:06 2011 +0000
6.2 +++ b/Hardware/LPC/W836XX.cs Wed Aug 31 22:48:49 2011 +0000
6.3 @@ -16,7 +16,7 @@
6.4
6.5 The Initial Developer of the Original Code is
6.6 Michael Möller <m.moeller@gmx.ch>.
6.7 - Portions created by the Initial Developer are Copyright (C) 2009-2010
6.8 + Portions created by the Initial Developer are Copyright (C) 2009-2011
6.9 the Initial Developer. All Rights Reserved.
6.10
6.11 Contributor(s):
6.12 @@ -50,6 +50,7 @@
6.13 private readonly float?[] voltages = new float?[0];
6.14 private readonly float?[] temperatures = new float?[0];
6.15 private readonly float?[] fans = new float?[0];
6.16 + private readonly float?[] controls = new float?[0];
6.17
6.18 private readonly bool[] peciTemperature = new bool[0];
6.19 private readonly byte[] voltageRegister = new byte[0];
6.20 @@ -110,7 +111,9 @@
6.21 }
6.22
6.23 public void WriteGPIO(int index, byte value) { }
6.24 -
6.25 +
6.26 + public void SetControl(int index, byte? value) { }
6.27 +
6.28 public W836XX(Chip chip, byte revision, ushort address) {
6.29 this.address = address;
6.30 this.revision = revision;
6.31 @@ -201,6 +204,7 @@
6.32 public float?[] Voltages { get { return voltages; } }
6.33 public float?[] Temperatures { get { return temperatures; } }
6.34 public float?[] Fans { get { return fans; } }
6.35 + public float?[] Controls { get { return controls; } }
6.36
6.37 public void Update() {
6.38 if (!Ring0.WaitIsaBusMutex(10))
7.1 --- a/Hardware/Mainboard/SuperIOHardware.cs Mon Aug 29 18:41:06 2011 +0000
7.2 +++ b/Hardware/Mainboard/SuperIOHardware.cs Wed Aug 31 22:48:49 2011 +0000
7.3 @@ -50,6 +50,7 @@
7.4 private readonly List<Sensor> voltages = new List<Sensor>();
7.5 private readonly List<Sensor> temperatures = new List<Sensor>();
7.6 private readonly List<Sensor> fans = new List<Sensor>();
7.7 + private readonly List<Sensor> controls = new List<Sensor>();
7.8
7.9 private delegate float? ReadValueDelegate(int index);
7.10 private delegate void UpdateDelegate();
7.11 @@ -58,6 +59,7 @@
7.12 private readonly ReadValueDelegate readVoltage;
7.13 private readonly ReadValueDelegate readTemperature;
7.14 private readonly ReadValueDelegate readFan;
7.15 + private readonly ReadValueDelegate readControl;
7.16
7.17 // delegate for post update mainboard specific code
7.18 private readonly UpdateDelegate postUpdate;
7.19 @@ -77,12 +79,14 @@
7.20 this.readVoltage = (index) => superIO.Voltages[index];
7.21 this.readTemperature = (index) => superIO.Temperatures[index];
7.22 this.readFan = (index) => superIO.Fans[index];
7.23 + this.readControl = (index) => superIO.Controls[index];
7.24
7.25 this.postUpdate = () => { };
7.26
7.27 List<Voltage> v = new List<Voltage>();
7.28 List<Temperature> t = new List<Temperature>();
7.29 List<Fan> f = new List<Fan>();
7.30 + List<Ctrl> c = new List<Ctrl>();
7.31
7.32 switch (superIO.Chip) {
7.33 case Chip.IT8712F:
7.34 @@ -870,6 +874,9 @@
7.35 f.Add(new Fan("CPU Fan", 1));
7.36 f.Add(new Fan("Power Fan", 2));
7.37 f.Add(new Fan("Chassis Fan #2", 3));
7.38 + c.Add(new Ctrl("Chassis Fan #2", 0));
7.39 + c.Add(new Ctrl("CPU Fan", 1));
7.40 + c.Add(new Ctrl("Chassis Fan #1", 2));
7.41 break;
7.42 case Model.P8P67_M_PRO: // NCT6776F
7.43 v.Add(new Voltage("CPU VCore", 0));
7.44 @@ -934,6 +941,8 @@
7.45 t.Add(new Temperature("Temperature #" + (i + 1), i));
7.46 for (int i = 0; i < superIO.Fans.Length; i++)
7.47 f.Add(new Fan("Fan #" + (i + 1), i));
7.48 + for (int i = 0; i < superIO.Controls.Length; i++)
7.49 + c.Add(new Ctrl("Fan Control #" + (i + 1), i));
7.50 break;
7.51 }
7.52
7.53 @@ -967,6 +976,30 @@
7.54 this, settings);
7.55 fans.Add(sensor);
7.56 }
7.57 +
7.58 + foreach (Ctrl ctrl in c) {
7.59 + int index = ctrl.Index;
7.60 + if (index < superIO.Controls.Length) {
7.61 + Sensor sensor = new Sensor(ctrl.Name, index, SensorType.Control,
7.62 + this, settings);
7.63 + Control control = new Control(sensor, settings, 0, 100);
7.64 + control.ControlModeChanged += (cc) => {
7.65 + if (cc.ControlMode == ControlMode.Default) {
7.66 + superIO.SetControl(index, null);
7.67 + } else {
7.68 + superIO.SetControl(index, (byte)(cc.SoftwareValue * 2.55));
7.69 + }
7.70 + };
7.71 + control.SoftwareControlValueChanged += (cc) => {
7.72 + if (cc.ControlMode == ControlMode.Software)
7.73 + superIO.SetControl(index, (byte)(cc.SoftwareValue * 2.55));
7.74 + };
7.75 + if (control.ControlMode == ControlMode.Software)
7.76 + superIO.SetControl(index, (byte)(control.SoftwareValue * 2.55));
7.77 + sensor.Control = control;
7.78 + controls.Add(sensor);
7.79 + }
7.80 + }
7.81 }
7.82
7.83 public override HardwareType HardwareType {
7.84 @@ -1011,9 +1044,25 @@
7.85 }
7.86 }
7.87
7.88 + foreach (Sensor sensor in controls) {
7.89 + float? value = readControl(sensor.Index);
7.90 + if (value.HasValue) {
7.91 + sensor.Value = value;
7.92 + ActivateSensor(sensor);
7.93 + }
7.94 + }
7.95 +
7.96 postUpdate();
7.97 }
7.98
7.99 + public override void Close() {
7.100 + foreach (Sensor sensor in controls) {
7.101 + // restore all controls back to default
7.102 + superIO.SetControl(sensor.Index, null);
7.103 + }
7.104 + base.Close();
7.105 + }
7.106 +
7.107 private class Voltage {
7.108 public readonly string Name;
7.109 public readonly int Index;
7.110 @@ -1064,5 +1113,15 @@
7.111 this.Index = index;
7.112 }
7.113 }
7.114 +
7.115 + private class Ctrl {
7.116 + public readonly string Name;
7.117 + public readonly int Index;
7.118 +
7.119 + public Ctrl(string name, int index) {
7.120 + this.Name = name;
7.121 + this.Index = index;
7.122 + }
7.123 + }
7.124 }
7.125 }