Improved Winbond temperature reading. Temperatures create by adding PECI Agent values (delta to TCC Activation Temperature) to a (possibly uncalibrated) TBase are not read. Direct reading temperatures from sensor report register if available. Added lower bound for temperatures on Winbond chips. Nvidia GPUs are now displayed even if they do not have any sensors.

This commit is contained in:
Michael Möller
2010-02-20 19:51:10 +00:00
parent d89b883632
commit bcb19ae527
4 changed files with 105 additions and 70 deletions
+67 -17
View File
@@ -67,8 +67,13 @@ namespace OpenHardwareMonitor.Hardware.LPC {
private const byte VOLTAGE_BASE_REG = 0x20;
private const byte BANK_SELECT_REGISTER = 0x4E;
private const byte VENDOR_ID_REGISTER = 0x4F;
private const byte TEMPERATURE_BASE_REG = 0x50;
private const byte TEMPERATURE_SYS_REG = 0x27;
private const byte TEMPERATURE_SOURCE_SELECT_REG = 0x49;
private string[] TEMPERATURE_NAME =
new string[] {"CPU", "Auxiliary", "System"};
private byte[] TEMPERATURE_REG = new byte[] { 0x50, 0x50, 0x27 };
private byte[] TEMPERATURE_BANK = new byte[] { 1, 2, 0 };
private byte[] TEMPERATURE_SEL = new byte[] { 1, 2, 0 };
private byte[] FAN_TACHO_REG = new byte[] { 0x28, 0x29, 0x2A, 0x3F, 0x53 };
private byte[] FAN_TACHO_BANK = new byte[] { 0, 0, 0, 0, 5 };
@@ -88,6 +93,17 @@ namespace OpenHardwareMonitor.Hardware.LPC {
(ushort)(address + DATA_REGISTER_OFFSET));
}
private void WriteByte(byte bank, byte register, byte value) {
WinRing0.WriteIoPortByte(
(ushort)(address + ADDRESS_REGISTER_OFFSET), BANK_SELECT_REGISTER);
WinRing0.WriteIoPortByte(
(ushort)(address + DATA_REGISTER_OFFSET), bank);
WinRing0.WriteIoPortByte(
(ushort)(address + ADDRESS_REGISTER_OFFSET), register);
WinRing0.WriteIoPortByte(
(ushort)(address + DATA_REGISTER_OFFSET), value);
}
public W836XX(Chip chip, byte revision, ushort address)
: base(chip)
{
@@ -96,10 +112,29 @@ namespace OpenHardwareMonitor.Hardware.LPC {
available = IsWinbondVendor();
temperatures = new Sensor[3];
temperatures[0] = new Sensor("CPU", 0, SensorType.Temperature, this);
temperatures[1] = new Sensor("Auxiliary", 1, SensorType.Temperature, this);
temperatures[2] = new Sensor("System", 2, SensorType.Temperature, this);
List<Sensor> list = new List<Sensor>();
switch (chip) {
case Chip.W83627DHG:
// do not add temperature sensor registers that read PECI agents
byte sel = ReadByte(0, TEMPERATURE_SOURCE_SELECT_REG);
if ((sel & 0x07) == 0)
list.Add(new Sensor(TEMPERATURE_NAME[0], 0,
SensorType.Temperature, this));
if ((sel & 0x70) == 0)
list.Add(new Sensor(TEMPERATURE_NAME[1], 1,
SensorType.Temperature, this));
list.Add(new Sensor(TEMPERATURE_NAME[2], 2,
SensorType.Temperature, this));
break;
default:
// no PECI support or extra sensor report register
for (int i = 0; i < TEMPERATURE_NAME.Length; i++) {
list.Add(new Sensor(TEMPERATURE_NAME[i], i,
SensorType.Temperature, this));
}
break;
}
temperatures = list.ToArray();
switch (chip) {
case Chip.W83627DHG:
@@ -145,6 +180,7 @@ namespace OpenHardwareMonitor.Hardware.LPC {
}
public void Update() {
foreach (Sensor sensor in voltages) {
if (sensor.Index < 7) {
int value = ReadByte(0, (byte)(VOLTAGE_BASE_REG + sensor.Index));
@@ -157,7 +193,7 @@ namespace OpenHardwareMonitor.Hardware.LPC {
// Battery voltage
bool valid = (ReadByte(0, 0x5D) & 0x01) > 0;
if (valid) {
sensor.Value =
sensor.Value =
0.008f * voltageGains[sensor.Index] * ReadByte(5, 0x51);
ActivateSensor(sensor);
} else
@@ -167,18 +203,32 @@ namespace OpenHardwareMonitor.Hardware.LPC {
foreach (Sensor sensor in temperatures) {
int value;
if (sensor.Index < 2) {
value = (sbyte)ReadByte((byte)(sensor.Index + 1), TEMPERATURE_BASE_REG);
value = (value << 1) | ReadByte((byte)(sensor.Index + 1),
(byte)(TEMPERATURE_BASE_REG + 1)) >> 7;
} else {
value = (sbyte)ReadByte(0, TEMPERATURE_SYS_REG) << 1;
switch (chip) {
case Chip.W83667HG:
case Chip.W83667HGB:
WriteByte(0, 0x7D, TEMPERATURE_SEL[sensor.Index]);
value = ((sbyte)ReadByte(0, 0x7E)) << 1;
break;
case Chip.W83627DHGP:
WriteByte(0, 0x7C, TEMPERATURE_SEL[sensor.Index]);
value = ((sbyte)ReadByte(0, 0x7D)) << 1;
break;
default:
value = ((sbyte)ReadByte(TEMPERATURE_BANK[sensor.Index],
TEMPERATURE_REG[sensor.Index])) << 1;
if (TEMPERATURE_BANK[sensor.Index] > 0) {
value |= ReadByte(TEMPERATURE_BANK[sensor.Index],
(byte)(TEMPERATURE_REG[sensor.Index] + 1)) >> 7;
}
break;
}
sensor.Value = value / 2.0f;
if (value < 0xFE)
float temperature = value / 2.0f;
if (temperature <= 125 && temperature >= -55) {
sensor.Value = temperature;
ActivateSensor(sensor);
else
} else {
DeactivateSensor(sensor);
}
}
long bits = 0;
@@ -212,7 +262,7 @@ namespace OpenHardwareMonitor.Hardware.LPC {
r.AppendLine();
r.AppendLine(" 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F");
r.AppendLine();
for (int i = 0; i < 0x7; i++) {
for (int i = 0; i <= 0x7; i++) {
r.Append(" "); r.Append((i << 4).ToString("X2")); r.Append(" ");
for (int j = 0; j <= 0xF; j++) {
r.Append(" ");
+34 -46
View File
@@ -50,55 +50,43 @@ namespace OpenHardwareMonitor.Hardware.Nvidia {
private Sensor[] temperatures;
private Sensor fan = null;
private bool available;
public NvidiaGPU(int adapterIndex, NvPhysicalGpuHandle handle) {
try {
string gpuName;
if (NVAPI.NvAPI_GPU_GetFullName(handle, out gpuName) == NvStatus.OK) {
this.name = "NVIDIA " + gpuName.Trim();
} else {
this.name = "NVIDIA";
}
this.icon = Utilities.EmbeddedResources.GetImage("nvidia.png");
this.adapterIndex = adapterIndex;
this.handle = handle;
NvGPUThermalSettings settings = GetThermalSettings();
temperatures = new Sensor[settings.Count];
for (int i = 0; i < temperatures.Length; i++) {
NvSensor sensor = settings.Sensor[i];
string name;
switch (sensor.Target) {
case NvThermalTarget.BOARD: name = "GPU Board"; break;
case NvThermalTarget.GPU: name = "GPU Core"; break;
case NvThermalTarget.MEMORY: name = "GPU Memory"; break;
case NvThermalTarget.POWER_SUPPLY: name = "GPU Power Supply"; break;
case NvThermalTarget.UNKNOWN: name = "GPU Unknown"; break;
default: name = "GPU"; break;
}
temperatures[i] = new Sensor(name, i, sensor.DefaultMaxTemp,
SensorType.Temperature, this);
ActivateSensor(temperatures[i]);
}
int value;
if (NVAPI.NvAPI_GPU_GetTachReading != null &&
NVAPI.NvAPI_GPU_GetTachReading(handle, out value) == NvStatus.OK) {
if (value > 0) {
fan = new Sensor("GPU", 0, SensorType.Fan, this);
ActivateSensor(fan);
}
}
available = temperatures.Length > 0 || fan != null;
} catch (Exception e) {
System.Windows.Forms.MessageBox.Show(e.Message + "\n" + e.StackTrace);
string gpuName;
if (NVAPI.NvAPI_GPU_GetFullName(handle, out gpuName) == NvStatus.OK) {
this.name = "NVIDIA " + gpuName.Trim();
} else {
this.name = "NVIDIA";
}
}
this.icon = Utilities.EmbeddedResources.GetImage("nvidia.png");
this.adapterIndex = adapterIndex;
this.handle = handle;
public bool IsAvailable {
get { return available; }
NvGPUThermalSettings settings = GetThermalSettings();
temperatures = new Sensor[settings.Count];
for (int i = 0; i < temperatures.Length; i++) {
NvSensor sensor = settings.Sensor[i];
string name;
switch (sensor.Target) {
case NvThermalTarget.BOARD: name = "GPU Board"; break;
case NvThermalTarget.GPU: name = "GPU Core"; break;
case NvThermalTarget.MEMORY: name = "GPU Memory"; break;
case NvThermalTarget.POWER_SUPPLY: name = "GPU Power Supply"; break;
case NvThermalTarget.UNKNOWN: name = "GPU Unknown"; break;
default: name = "GPU"; break;
}
temperatures[i] = new Sensor(name, i, sensor.DefaultMaxTemp,
SensorType.Temperature, this);
ActivateSensor(temperatures[i]);
}
int value;
if (NVAPI.NvAPI_GPU_GetTachReading != null &&
NVAPI.NvAPI_GPU_GetTachReading(handle, out value) == NvStatus.OK) {
if (value > 0) {
fan = new Sensor("GPU", 0, SensorType.Fan, this);
ActivateSensor(fan);
}
}
}
public string Name {
+2 -5
View File
@@ -64,11 +64,8 @@ namespace OpenHardwareMonitor.Hardware.Nvidia {
report.AppendLine(count.ToString());
report.AppendLine();
for (int i = 0; i < count; i++) {
NvidiaGPU gpu = new NvidiaGPU(i, handles[i]);
if (gpu.IsAvailable)
hardware.Add(gpu);
}
for (int i = 0; i < count; i++)
hardware.Add(new NvidiaGPU(i, handles[i]));
}
public IHardware[] Hardware {
+2 -2
View File
@@ -69,5 +69,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("0.1.22.0")]
[assembly: AssemblyFileVersion("0.1.22.0")]
[assembly: AssemblyVersion("0.1.22.1")]
[assembly: AssemblyFileVersion("0.1.22.1")]