I've reverse engineered a Windows SMBus driver in order to port the code to a Linux system. In order to interact with the SMBus, the code uses hard coded port addresses based on the system chipset. In my case I'm using an AMD X470 with a base address of 0xB20.
Every SMBus transaction terminates with a call to the following function:
BOOL f_10CB0 (BYTE arg1) {
BYTE val;
for (int i = 0; i < 0x8000; ++i) {
val = ReadPort(this->wPort);
// Break on any error (bits 1:4) or bit 7 (bit 7 is reserved???)
if (val & 0x9E)
break;
// Why is this port being read?
ReadPort(0xED);
}
if ((val & 0x82) == 0) // 0x80 == unknown, 0x02 == Bus Interrupt
return (val & 0x1C) == 0; // 0x04 (DeviceError) | 0x08 (BusCollision) | 0x10 (Killed)
ReadPort(this->wPort);
return FALSE;
}
Note, the above is pseudo-code and this question is language agnostic.
I have two problems with the code.
- It's testing bit 7 of the status register
0xB20
. The docs state bits 5:7 are reserved. Am I reading the wrong docs? Does anybody know what this bit signifies? - The loop reads a hard coded port
0xED
for which I cannot find any documentation. The call always returns0xFF
but the address doesn't appear to be valid on my system.
With regards to problem 2, I found an obscure reference to the port on a chromium-os mailing list which uses it to prevent IO delay from writing to port 0x80. Is 0xED a reserved address of any kind?