134 lines
4.7 KiB
C
134 lines
4.7 KiB
C
#include "../hooks/setupapi_.h"
|
|
#include "../lib/dmi/dmi.h"
|
|
#include "mx.h"
|
|
#include "smbus.h"
|
|
|
|
smbus_callback_t* smbus_devices[256] = { NULL };
|
|
|
|
void smbus_install(BYTE v_addr, smbus_callback_t* write, smbus_callback_t* read) {
|
|
smbus_devices[v_addr << 1] = write;
|
|
smbus_devices[(v_addr << 1) + 1] = read;
|
|
}
|
|
|
|
BOOL handle_smbus(BYTE command, WORD v_addr, WORD command_code, BYTE nbytes, BYTE* data) {
|
|
WORD p_addr = (v_addr & 0x7fff) << 1;
|
|
ich9_cmd_t smb_cmd = ICH9_CMD_QUICK;
|
|
switch (command) {
|
|
case MXSMBUS_CMD_WRITE_QUICK:
|
|
break;
|
|
case MXSMBUS_CMD_READ_QUICK:
|
|
p_addr++;
|
|
break;
|
|
case MXSMBUS_CMD_WRITE_BYTE:
|
|
smb_cmd = ICH9_CMD_BYTE;
|
|
break;
|
|
case MXSMBUS_CMD_READ_BYTE:
|
|
p_addr++;
|
|
smb_cmd = ICH9_CMD_BYTE;
|
|
break;
|
|
case MXSMBUS_CMD_WRITE_BYTE_DATA:
|
|
smb_cmd = ICH9_CMD_BYTE_DATA;
|
|
break;
|
|
case MXSMBUS_CMD_READ_BYTE_DATA:
|
|
p_addr++;
|
|
smb_cmd = ICH9_CMD_BYTE_DATA;
|
|
break;
|
|
case MXSMBUS_CMD_WRITE_WORD_DATA:
|
|
smb_cmd = ICH9_CMD_WORD_DATA;
|
|
break;
|
|
case MXSMBUS_CMD_READ_WORD_DATA:
|
|
p_addr++;
|
|
smb_cmd = ICH9_CMD_WORD_DATA;
|
|
break;
|
|
case MXSMBUS_CMD_WRITE_BLOCK:
|
|
smb_cmd = ICH9_CMD_BLOCK;
|
|
break;
|
|
case MXSMBUS_CMD_READ_BLOCK:
|
|
p_addr++;
|
|
smb_cmd = ICH9_CMD_BLOCK;
|
|
break;
|
|
case MXSMBUS_CMD_PROCESS_CALL:
|
|
smb_cmd = ICH9_CMD_PROCESS_CALL;
|
|
break;
|
|
case MXSMBUS_CMD_I2C:
|
|
smb_cmd = ICH9_CMD_I2C_READ;
|
|
break;
|
|
}
|
|
|
|
log_trace(plfMxSmbus, "Making request to %02X (virtual: %04X/%04x, cmd: %01X, code: %04X)", p_addr,
|
|
v_addr, command, smb_cmd, command_code);
|
|
|
|
smbus_callback_t* callback = smbus_devices[p_addr];
|
|
if (callback == NULL) {
|
|
log_error(plfMxSmbus, "Request to unregistered address: %02x", p_addr);
|
|
return FALSE;
|
|
}
|
|
return (*callback)(smb_cmd, command_code, nbytes, data);
|
|
}
|
|
|
|
BOOL WINAPI mxsmbus_DeviceIoControl(file_context_t* ctx, DWORD dwIoControlCode, LPVOID lpInBuffer,
|
|
DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize,
|
|
LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped) {
|
|
// Default value
|
|
if (lpBytesReturned) *lpBytesReturned = nOutBufferSize;
|
|
|
|
switch (dwIoControlCode) {
|
|
case IOCTL_MXSMBUS_GET_VERSION:
|
|
log_misc(plfMxSmbus,
|
|
"DeviceIoControl(<mxsmbus>, <get version>, 0x%p, 0x%x, "
|
|
"-, 0x%x, -, -)",
|
|
lpInBuffer, nInBufferSize, nOutBufferSize);
|
|
|
|
((LPDWORD)lpOutBuffer)[0] = 0x01020001;
|
|
if (lpBytesReturned) *lpBytesReturned = 4;
|
|
break;
|
|
case IOCTL_MXSMBUS_I2C: {
|
|
// BYTE command = ((BYTE*)lpInBuffer)[1];
|
|
PMXSMBUS_I2C_PACKET packet = (PMXSMBUS_I2C_PACKET)lpInBuffer;
|
|
BYTE command = packet->command;
|
|
if (command > 10) {
|
|
((BYTE*)lpOutBuffer)[0] = 0x19;
|
|
return FALSE;
|
|
}
|
|
if (handle_smbus(command, packet->v_addr & 0x7fff, packet->command_code, packet->nbytes, packet->data)) {
|
|
((BYTE*)lpOutBuffer)[0] = 0x00;
|
|
return TRUE;
|
|
} else {
|
|
((BYTE*)lpOutBuffer)[0] = 0x01;
|
|
return FALSE;
|
|
};
|
|
}
|
|
case IOCTL_MXSMBUS_REQUEST: {
|
|
// BYTE command = ((BYTE*)lpInBuffer)[1];
|
|
PMXSMBUS_REQUEST_PACKET packet = (PMXSMBUS_REQUEST_PACKET)lpInBuffer;
|
|
BYTE command = packet->command;
|
|
if (command > 11) {
|
|
((BYTE*)lpOutBuffer)[0] = 0x19;
|
|
return FALSE;
|
|
}
|
|
if (handle_smbus(command, packet->v_addr & 0x7f, packet->command_code, packet->nbytes, packet->data)) {
|
|
((BYTE*)lpOutBuffer)[0] = 0x00;
|
|
return TRUE;
|
|
} else {
|
|
((BYTE*)lpOutBuffer)[0] = 0x01;
|
|
return FALSE;
|
|
};
|
|
}
|
|
default:
|
|
log_warning(plfMxSmbus, "unhandled 0x%08x", dwIoControlCode);
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
void setup_mxsmbus() {
|
|
file_hook_t* mxsmbus = new_file_hook(L"\\\\.\\mxsmbus");
|
|
mxsmbus->DeviceIoControl = &mxsmbus_DeviceIoControl;
|
|
|
|
hook_file(mxsmbus);
|
|
|
|
if (!add_fake_device(&MXSMBUS_GUID, L"\\\\.\\mxsmbus")) {
|
|
log_error(plfMxSmbus, "failed to install mxsmbus device");
|
|
}
|
|
}
|