Added code to read the additional fans on the ASRock P55 Deluxe mainboard via special GPIO switching.
This commit is contained in:
@@ -65,6 +65,12 @@ namespace OpenHardwareMonitor.Hardware.LPC {
|
||||
return WinRing0.ReadIoPortByte((ushort)(address + DATA_REGISTER_OFFSET));
|
||||
}
|
||||
|
||||
public byte? ReadGPIO(int index) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void WriteGPIO(int index, byte value) { }
|
||||
|
||||
public F718XX(Chip chip, ushort address) {
|
||||
this.address = address;
|
||||
this.chip = chip;
|
||||
|
||||
@@ -44,6 +44,9 @@ namespace OpenHardwareMonitor.Hardware.LPC {
|
||||
float?[] Temperatures { get; }
|
||||
float?[] Fans { get; }
|
||||
|
||||
byte? ReadGPIO(int index);
|
||||
void WriteGPIO(int index, byte value);
|
||||
|
||||
string GetReport();
|
||||
void Update();
|
||||
}
|
||||
|
||||
+47
-3
@@ -45,6 +45,9 @@ namespace OpenHardwareMonitor.Hardware.LPC {
|
||||
private readonly Chip chip;
|
||||
private readonly byte version;
|
||||
|
||||
private readonly ushort gpioAddress;
|
||||
private readonly int gpioCount;
|
||||
|
||||
private readonly ushort addressReg;
|
||||
private readonly ushort dataReg;
|
||||
|
||||
@@ -77,16 +80,31 @@ namespace OpenHardwareMonitor.Hardware.LPC {
|
||||
byte value = WinRing0.ReadIoPortByte(dataReg);
|
||||
valid = register == WinRing0.ReadIoPortByte(addressReg);
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
public IT87XX(Chip chip, ushort address, byte version) {
|
||||
public byte? ReadGPIO(int index) {
|
||||
if (index >= gpioCount)
|
||||
return null;
|
||||
|
||||
return WinRing0.ReadIoPortByte((ushort)(gpioAddress + index));
|
||||
}
|
||||
|
||||
public void WriteGPIO(int index, byte value) {
|
||||
if (index >= gpioCount)
|
||||
return;
|
||||
|
||||
WinRing0.WriteIoPortByte((ushort)(gpioAddress + index), value);
|
||||
}
|
||||
|
||||
public IT87XX(Chip chip, ushort address, ushort gpioAddress, byte version) {
|
||||
|
||||
this.address = address;
|
||||
this.chip = chip;
|
||||
this.version = version;
|
||||
this.addressReg = (ushort)(address + ADDRESS_REGISTER_OFFSET);
|
||||
this.dataReg = (ushort)(address + DATA_REGISTER_OFFSET);
|
||||
|
||||
this.gpioAddress = gpioAddress;
|
||||
|
||||
// Check vendor id
|
||||
bool valid;
|
||||
byte vendorId = ReadByte(VENDOR_ID_REGISTER, out valid);
|
||||
@@ -109,6 +127,20 @@ namespace OpenHardwareMonitor.Hardware.LPC {
|
||||
} else {
|
||||
voltageGain = 0.016f;
|
||||
}
|
||||
|
||||
// Set the number of GPIO sets
|
||||
switch (chip) {
|
||||
case Chip.IT8712F:
|
||||
case Chip.IT8716F:
|
||||
case Chip.IT8718F:
|
||||
case Chip.IT8726F:
|
||||
gpioCount = 5;
|
||||
break;
|
||||
case Chip.IT8720F:
|
||||
case Chip.IT8721F:
|
||||
gpioCount = 8;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public Chip Chip { get { return chip; } }
|
||||
@@ -126,6 +158,8 @@ namespace OpenHardwareMonitor.Hardware.LPC {
|
||||
version.ToString("X", CultureInfo.InvariantCulture));
|
||||
r.Append("Base Address: 0x"); r.AppendLine(
|
||||
address.ToString("X4", CultureInfo.InvariantCulture));
|
||||
r.Append("GPIO Address: 0x"); r.AppendLine(
|
||||
gpioAddress.ToString("X4", CultureInfo.InvariantCulture));
|
||||
r.AppendLine();
|
||||
|
||||
if (!WinRing0.WaitIsaBusMutex(100))
|
||||
@@ -150,6 +184,16 @@ namespace OpenHardwareMonitor.Hardware.LPC {
|
||||
}
|
||||
r.AppendLine();
|
||||
|
||||
r.AppendLine("GPIO Registers");
|
||||
r.AppendLine();
|
||||
for (int i = 0; i < gpioCount; i++) {
|
||||
r.Append(" ");
|
||||
r.Append(ReadGPIO(i).Value.ToString("X2",
|
||||
CultureInfo.InvariantCulture));
|
||||
}
|
||||
r.AppendLine();
|
||||
r.AppendLine();
|
||||
|
||||
WinRing0.ReleaseIsaBusMutex();
|
||||
|
||||
return r.ToString();
|
||||
|
||||
@@ -141,6 +141,12 @@ namespace OpenHardwareMonitor.Hardware.LPC {
|
||||
fanReaders[i] = new StreamReader(fanPaths[i]);
|
||||
}
|
||||
|
||||
public byte? ReadGPIO(int index) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void WriteGPIO(int index, byte value) { }
|
||||
|
||||
public string GetReport() {
|
||||
return null;
|
||||
}
|
||||
|
||||
+28
-11
@@ -64,10 +64,10 @@ namespace OpenHardwareMonitor.Hardware.LPC {
|
||||
private byte ReadByte(byte register) {
|
||||
WinRing0.WriteIoPortByte(registerPort, register);
|
||||
return WinRing0.ReadIoPortByte(valuePort);
|
||||
}
|
||||
}
|
||||
|
||||
private ushort ReadWord(byte register) {
|
||||
return (ushort)((ReadByte(register) << 8) |
|
||||
return (ushort)((ReadByte(register) << 8) |
|
||||
ReadByte((byte)(register + 1)));
|
||||
}
|
||||
|
||||
@@ -218,7 +218,7 @@ namespace OpenHardwareMonitor.Hardware.LPC {
|
||||
if (id != 0 && id != 0xff) {
|
||||
WinbondFintekExit();
|
||||
|
||||
ReportUnknownChip("Winbond / Fintek", ((id << 8) | revision));
|
||||
ReportUnknownChip("Winbond / Fintek", ((id << 8) | revision));
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -235,7 +235,7 @@ namespace OpenHardwareMonitor.Hardware.LPC {
|
||||
report.Append("Chip ID: 0x");
|
||||
report.AppendLine(chip.ToString("X"));
|
||||
report.Append("Chip revision: 0x");
|
||||
report.AppendLine(revision.ToString("X",
|
||||
report.AppendLine(revision.ToString("X",
|
||||
CultureInfo.InvariantCulture));
|
||||
report.AppendLine("Error: Address verification failed");
|
||||
report.AppendLine();
|
||||
@@ -250,10 +250,10 @@ namespace OpenHardwareMonitor.Hardware.LPC {
|
||||
report.Append("Chip ID: 0x");
|
||||
report.AppendLine(chip.ToString("X"));
|
||||
report.Append("Chip revision: 0x");
|
||||
report.AppendLine(revision.ToString("X",
|
||||
report.AppendLine(revision.ToString("X",
|
||||
CultureInfo.InvariantCulture));
|
||||
report.Append("Error: Invalid address 0x");
|
||||
report.AppendLine(address.ToString("X",
|
||||
report.AppendLine(address.ToString("X",
|
||||
CultureInfo.InvariantCulture));
|
||||
report.AppendLine();
|
||||
return false;
|
||||
@@ -280,10 +280,10 @@ namespace OpenHardwareMonitor.Hardware.LPC {
|
||||
report.Append("Chip ID: 0x");
|
||||
report.AppendLine(chip.ToString("X"));
|
||||
report.Append("Chip revision: 0x");
|
||||
report.AppendLine(revision.ToString("X",
|
||||
report.AppendLine(revision.ToString("X",
|
||||
CultureInfo.InvariantCulture));
|
||||
report.Append("Error: Invalid vendor ID 0x");
|
||||
report.AppendLine(vendorID.ToString("X",
|
||||
report.AppendLine(vendorID.ToString("X",
|
||||
CultureInfo.InvariantCulture));
|
||||
report.AppendLine();
|
||||
return false;
|
||||
@@ -304,6 +304,7 @@ namespace OpenHardwareMonitor.Hardware.LPC {
|
||||
#region ITE
|
||||
|
||||
private const byte IT87_ENVIRONMENT_CONTROLLER_LDN = 0x04;
|
||||
private const byte IT87_GPIO_LDN = 0x07;
|
||||
private const byte IT87_CHIP_VERSION_REGISTER = 0x22;
|
||||
|
||||
private void IT87Enter() {
|
||||
@@ -351,6 +352,11 @@ namespace OpenHardwareMonitor.Hardware.LPC {
|
||||
|
||||
byte version = (byte)(ReadByte(IT87_CHIP_VERSION_REGISTER) & 0x0F);
|
||||
|
||||
Select(IT87_GPIO_LDN);
|
||||
ushort gpioAddress = ReadWord(BASE_ADDRESS_REGISTER + 2);
|
||||
Thread.Sleep(1);
|
||||
ushort gpioVerify = ReadWord(BASE_ADDRESS_REGISTER + 2);
|
||||
|
||||
IT87Exit();
|
||||
|
||||
if (address != verify || address < 0x100 || (address & 0xF007) != 0) {
|
||||
@@ -363,7 +369,18 @@ namespace OpenHardwareMonitor.Hardware.LPC {
|
||||
return false;
|
||||
}
|
||||
|
||||
superIOs.Add(new IT87XX(chip, address, version));
|
||||
if (gpioAddress != gpioVerify || gpioAddress < 0x100 ||
|
||||
(gpioAddress & 0xF007) != 0) {
|
||||
report.Append("Chip ID: 0x");
|
||||
report.AppendLine(chip.ToString("X"));
|
||||
report.Append("Error: Invalid GPIO address 0x");
|
||||
report.AppendLine(gpioAddress.ToString("X",
|
||||
CultureInfo.InvariantCulture));
|
||||
report.AppendLine();
|
||||
return false;
|
||||
}
|
||||
|
||||
superIOs.Add(new IT87XX(chip, address, gpioAddress, version));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -417,7 +434,7 @@ namespace OpenHardwareMonitor.Hardware.LPC {
|
||||
if (DetectIT87()) continue;
|
||||
|
||||
if (DetectSMSC()) continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public LPCIO() {
|
||||
@@ -429,7 +446,7 @@ namespace OpenHardwareMonitor.Hardware.LPC {
|
||||
|
||||
Detect();
|
||||
|
||||
WinRing0.ReleaseIsaBusMutex();
|
||||
WinRing0.ReleaseIsaBusMutex();
|
||||
}
|
||||
|
||||
public ISuperIO[] SuperIO {
|
||||
|
||||
@@ -104,6 +104,12 @@ namespace OpenHardwareMonitor.Hardware.LPC {
|
||||
WinRing0.WriteIoPortByte(
|
||||
(ushort)(address + DATA_REGISTER_OFFSET), value);
|
||||
}
|
||||
|
||||
public byte? ReadGPIO(int index) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void WriteGPIO(int index, byte value) { }
|
||||
|
||||
public W836XX(Chip chip, byte revision, ushort address) {
|
||||
this.address = address;
|
||||
|
||||
@@ -35,8 +35,10 @@
|
||||
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Threading;
|
||||
using OpenHardwareMonitor.Hardware.LPC;
|
||||
|
||||
namespace OpenHardwareMonitor.Hardware.Mainboard {
|
||||
@@ -50,6 +52,20 @@ namespace OpenHardwareMonitor.Hardware.Mainboard {
|
||||
private readonly List<Sensor> temperatures = new List<Sensor>();
|
||||
private readonly List<Sensor> fans = new List<Sensor>();
|
||||
|
||||
private delegate float? ReadValueDelegate(int index);
|
||||
private delegate void UpdateDelegate();
|
||||
|
||||
// delegates for mainboard specific sensor reading code
|
||||
private readonly ReadValueDelegate readVoltage;
|
||||
private readonly ReadValueDelegate readTemperature;
|
||||
private readonly ReadValueDelegate readFan;
|
||||
|
||||
// delegate for post update mainboard specific code
|
||||
private readonly UpdateDelegate postUpdate;
|
||||
|
||||
// mainboard specific mutex
|
||||
private readonly Mutex mutex;
|
||||
|
||||
public SuperIOHardware(Mainboard mainboard, ISuperIO superIO,
|
||||
Manufacturer manufacturer, Model model, ISettings settings)
|
||||
{
|
||||
@@ -57,6 +73,12 @@ namespace OpenHardwareMonitor.Hardware.Mainboard {
|
||||
this.superIO = superIO;
|
||||
this.name = ChipName.GetName(superIO.Chip);
|
||||
|
||||
this.readVoltage = (index) => superIO.Voltages[index];
|
||||
this.readTemperature = (index) => superIO.Temperatures[index];
|
||||
this.readFan = (index) => superIO.Fans[index];
|
||||
|
||||
this.postUpdate = () => { };
|
||||
|
||||
List<Voltage> v = new List<Voltage>();
|
||||
List<Temperature> t = new List<Temperature>();
|
||||
List<Fan> f = new List<Fan>();
|
||||
@@ -119,6 +141,7 @@ namespace OpenHardwareMonitor.Hardware.Mainboard {
|
||||
case Manufacturer.ASRock:
|
||||
switch (model) {
|
||||
case Model.P55_Deluxe: // IT8720F
|
||||
|
||||
v.Add(new Voltage("CPU VCore", 0));
|
||||
v.Add(new Voltage("+3.3V", 2));
|
||||
v.Add(new Voltage("+12V", 4, 30, 10));
|
||||
@@ -128,8 +151,54 @@ namespace OpenHardwareMonitor.Hardware.Mainboard {
|
||||
t.Add(new Temperature("Motherboard", 1));
|
||||
f.Add(new Fan("CPU Fan", 0));
|
||||
f.Add(new Fan("Chassis Fan #1", 1));
|
||||
// fan channel 2 can connect to 3 different fan headers
|
||||
// which fan is read is configured with gpio 83-85
|
||||
|
||||
// this mutex is also used by the official ASRock tool
|
||||
mutex = new Mutex(false, "ASRockOCMark");
|
||||
|
||||
bool exclusiveAccess = false;
|
||||
try {
|
||||
exclusiveAccess = mutex.WaitOne(10, false);
|
||||
} catch (AbandonedMutexException) { }
|
||||
catch (InvalidOperationException) { }
|
||||
|
||||
// only read additional fans if we get exclusive access
|
||||
if (exclusiveAccess) {
|
||||
|
||||
f.Add(new Fan("Chassis Fan #2", 2));
|
||||
f.Add(new Fan("Chassis Fan #3", 3));
|
||||
f.Add(new Fan("Power Fan", 4));
|
||||
|
||||
readFan = (index) => {
|
||||
if (index < 2) {
|
||||
return superIO.Fans[index];
|
||||
} else {
|
||||
// get GPIO 80-87
|
||||
byte? gpio = superIO.ReadGPIO(7);
|
||||
if (!gpio.HasValue)
|
||||
return null;
|
||||
|
||||
// read the last 3 fans based on GPIO 83-85
|
||||
int[] masks = { 0x05, 0x03, 0x06 };
|
||||
return (((gpio.Value >> 3) & 0x07) ==
|
||||
masks[index - 2]) ? superIO.Fans[2] : null;
|
||||
}
|
||||
};
|
||||
|
||||
int fanIndex = 0;
|
||||
postUpdate = () => {
|
||||
// get GPIO 80-87
|
||||
byte? gpio = superIO.ReadGPIO(7);
|
||||
if (!gpio.HasValue)
|
||||
return;
|
||||
|
||||
// prepare the GPIO 83-85 for the next update
|
||||
int[] masks = { 0x05, 0x03, 0x06 };
|
||||
superIO.WriteGPIO(7,
|
||||
(byte)((gpio.Value & 0xC7) | (masks[fanIndex] << 3)));
|
||||
fanIndex = (fanIndex + 1) % 3;
|
||||
};
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
v.Add(new Voltage("CPU VCore", 0));
|
||||
@@ -741,7 +810,7 @@ namespace OpenHardwareMonitor.Hardware.Mainboard {
|
||||
superIO.Update();
|
||||
|
||||
foreach (Sensor sensor in voltages) {
|
||||
float? value = superIO.Voltages[sensor.Index];
|
||||
float? value = readVoltage(sensor.Index);
|
||||
if (value.HasValue) {
|
||||
sensor.Value = value + (value - sensor.Parameters[2].Value) *
|
||||
sensor.Parameters[0].Value / sensor.Parameters[1].Value;
|
||||
@@ -750,7 +819,7 @@ namespace OpenHardwareMonitor.Hardware.Mainboard {
|
||||
}
|
||||
|
||||
foreach (Sensor sensor in temperatures) {
|
||||
float? value = superIO.Temperatures[sensor.Index];
|
||||
float? value = readTemperature(sensor.Index);
|
||||
if (value.HasValue) {
|
||||
sensor.Value = value + sensor.Parameters[0].Value;
|
||||
ActivateSensor(sensor);
|
||||
@@ -758,13 +827,15 @@ namespace OpenHardwareMonitor.Hardware.Mainboard {
|
||||
}
|
||||
|
||||
foreach (Sensor sensor in fans) {
|
||||
float? value = superIO.Fans[sensor.Index];
|
||||
float? value = readFan(sensor.Index);
|
||||
if (value.HasValue) {
|
||||
sensor.Value = value;
|
||||
if (value.Value > 0)
|
||||
ActivateSensor(sensor);
|
||||
}
|
||||
}
|
||||
|
||||
postUpdate();
|
||||
}
|
||||
|
||||
private class Voltage {
|
||||
|
||||
Reference in New Issue
Block a user