Added code to read the additional fans on the ASRock P55 Deluxe mainboard via special GPIO switching.

This commit is contained in:
Michael Möller
2010-10-17 16:04:19 +00:00
parent cac6928f07
commit 69e708b7d6
7 changed files with 172 additions and 19 deletions
+6
View File
@@ -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;
+3
View File
@@ -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
View File
@@ -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();
+6
View File
@@ -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
View File
@@ -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 {
+6
View File
@@ -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;
+76 -5
View File
@@ -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 {