Search code examples
c#open-sourcehardwaremonitoringbus

Can you piece together the following clues to help me read temperatures out of the Winbond W83793 chip?


I am trying to get OpenHardwareMonitor to read temperature data out of the Winbond W83793 chip on my Supermicro X7DWA motherboard. The problem is that I don't have any low-level programming experience, and the available docs online do not seem to be sufficient in explaining how to access the temperatures.

However, over the month that I've been working on this problem, I have discovered a few values and low-level methods that may be the key to solving my problem. I just need to figure out how to use them to get what I want. That's where I turn to you, because you might understand what this information means, and how to apply it, unlike me. I've already done my fair share of poking around, resulting in many blue screens and computer restarts. Enough guessing, I need to piece these clues together. Here is what I know so far:

  1. To read from the chip, I will somehow need to access the SMBus, because that is the way monitoring programs, such as CPUID HWMonitor, are getting the information. OpenHardwareMonitor, as far as I know, does not have any code in it to access the SMBus, which is why it may not be reading from the chip. However, OpenHardwareMonitor has the following methods included in its Ring0 class, which it uses to access information from other chips. I may be able to use these methods to my advantage:

    void Ring0.WriteIOPort(uint port, byte value);
    byte Ring0.ReadIOPort(uint port);
    
  2. Among other information, HWMonitor reports the following information about the Winbond W83793 chip to me when I save a report:

    Register Space: SMBus, base address = 0x01100

    SMBus request: channel 0x0, address 0x2F

    It looks like these are important values, but I don't know exactly what they mean, and how I can use them in conjunction with the Ring0 methods above. Hmm... so many clues. The other values HWMonitor shows me are the actual voltages, temperatures, and fan speeds, and an array of hexadecimal values that represents data from somewhere on the chip, which I will reproduce here if you want to look at it.

  3. Finally, in the W83793 data sheet, on page 53 (if you have the document open), here are the addresses in hex of the temperatures I would like to read (I believe):

    TD1 Readout - Bank 0 Address 1C

    TD2 Readout - Bank 0 Address 1D

    TD3 Readout - Bank 0 Address 1E

    TD4 Readout - Bank 0 Address 1F

    Low bit Readout - Bank 0 Address 22

    TR1 Readout - Bank 0 Address 20

    TR2 Readout - Bank 0 Address 21

That is all I know so far. The OpenHardwareMonitor, W83793 chip, and Ring0 code are available via the links provided above. As I said earlier, I've been at it for a month, and I just haven't been able to solve this mystery yet. I hope you can help me. All this information may seem a bit intimidating, but I'm sure it will make sense to someone with some low-level programming experience.

To summarize my question, use the clues provided above to figure out how to get OpenHardwareMonitor to read temperatures out of the W83793 chip. I don't need details on creating a chip in OpenHardwareMonitor. I already have a class ready. I just need the sequence and format to write Ring0 commands in, if that's what I need to do.

EDIT: I found some more information. I printed an SMBus device report from HWMonitor, and among other things, I got this line, included here because it says 0x2F:

SMB device: I/O = 0x1100, address 0x2F, channel = 0

This must mean I need to somehow combine the addresses of the I/O with the address of the chip, which seems to be 0x2F. I tried adding them together but then I get all temperature readings to be 255, so that wasn't the right guess.


Solution

  • In the end, the author of OpenHardwareMonitor kindly helped me out, and now I'm able to read temperatures out of my chip. While the entire solution to this problem is a little more complex and is still beyond me, here is the basic reading and writing using the Ring0 class, for anyone interested. Note that this is specific to my machine and chip. For you, the base address and slave address may be different, but you can find them using CPUID HWMonitor, by printing a report.

    First, here are the constants that were used:

    private const int   BASE_ADDRESS    = 0x1100;
    private const uint  SLAVE_ADDRESS   = 0X2F; // as we figured out already
    private const byte  HOST_STAT_REG   = 0;    // host status register
    private const byte  HOST_BUSY       = 1;    
    private const byte  HOST_CTRL_REG   = 2;    // host control register
    private const byte  HOST_CMD_REG    = 3;    // host command register
    private const byte  T_SLAVE_ADR_REG = 4;    // transmit slave address register
    private const byte  HOST_DATA_0_REG = 5;  
    private const byte  BYTE_DATA_COMM  = 0x08; // byte data command
    private const byte  START_COMM      = 0x40; // start command
    private const byte  READ            = 1;
    private const byte  WRITE           = 0;
    

    Next, here is the basic code to read a particular byte from a register on the chip:

    // first wait until ready
    byte status;
    do
    {
      status = Ring0.ReadIoPort(BASE_ADDRESS + HOST_STAT_REG);
    } while ((status & HOST_BUSY) > 0);
    if ((status & 0x1E) != 0)
    {
      Ring0.WriteIoPort(BASE_ADDRESS + HOST_STAT_REG, status);
    }
    
    // now get the value
    Ring0.WriteIoPort(BASE_ADDRESS + HOST_DATA_0_REG, 0);
    Ring0.WriteIoPort(BASE_ADDRESS + HOST_COMM_REG, theRegister)
    Ring0.WriteIoPort(BASE_ADDRESS + T_SLAVE_ADR_REG, 
                (byte)((SLAVE_ADDRESS << 1) | READ));
    Ring0.WriteIoPort(BASE_ADDRESS + HOST_CTRL_REG,
                START_COMM | BYTE_DATA_COMM);
    Ring0.ReadIoPort(BASE_ADDRESS + HOST_DATA_0_REGISTER); // this returns the value
    
    // now wait for it to end
    while ((Ring0.ReadIoPort(BASE_ADDRESS + HOST_STAT_REG) & HOST_BUSY) > 0) {}
    

    While I don't understand it that well, this could serve as a rough guide to someone with more low-level experience than me who is having a similar problem.