micetools/src/micetools/lib/am/amEeprom.c

389 lines
13 KiB
C

#include "amEeprom.h"
#pragma comment(lib, "Setupapi.lib")
#include "../../dll/smbus.h"
#include "../ami/ami.h"
AM_LIB_C_HEADER(amEeprom, AM_EEPROM)
HANDLE amEepromCreateDeviceFile(const GUID *guid, LPCSTR resource, DWORD member_index) {
SP_DEVICE_INTERFACE_DATA interfaceData;
SP_DEVICE_INTERFACE_DETAIL_DATA_A interfaceDetail[204];
if (!guid) {
if (amEepromDebugLevel > 0) amiDebugLog("PARAM Error.");
return INVALID_HANDLE_VALUE;
}
HDEVINFO DeviceInfoSet =
SetupDiGetClassDevsA(guid, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
if (DeviceInfoSet == INVALID_HANDLE_VALUE) {
if (amEepromDebugLevel > 0) amiDebugLog("SetupDiGetClassDevs Error(%ld).", GetLastError());
return INVALID_HANDLE_VALUE;
}
interfaceData.cbSize = 28;
BOOL s;
s = SetupDiEnumDeviceInterfaces(DeviceInfoSet, NULL, guid, member_index, &interfaceData);
if (!s) {
if (amEepromDebugLevel > 0)
amiDebugLog("SetupDiEnumDeviceInterfaces Error(%ld).", GetLastError());
SetupDiDestroyDeviceInfoList(DeviceInfoSet);
return INVALID_HANDLE_VALUE;
}
interfaceDetail[0].cbSize = 5;
s = SetupDiGetDeviceInterfaceDetailA(DeviceInfoSet, &interfaceData, interfaceDetail,
sizeof interfaceDetail, NULL, NULL);
if (!s) {
if (amEepromDebugLevel > 0)
amiDebugLog("SetupDiGetDeviceInterfaceDetailA Error(%ld).", GetLastError());
SetupDiDestroyDeviceInfoList(DeviceInfoSet);
return INVALID_HANDLE_VALUE;
}
char fileName[260];
strcpy_s(fileName, sizeof fileName, interfaceDetail[0].DevicePath);
if (resource != NULL) {
strcat_s(fileName, 4, "\\");
strcat_s(fileName, 4, resource);
}
HANDLE device =
CreateFileA(fileName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, FILE_SUPPORTS_GHOSTING, NULL);
SetupDiDestroyDeviceInfoList(DeviceInfoSet);
return device;
}
AM_EEPROM_STATUS amEepromGetDriverVersion(AM_EEPROM *device, LPDWORD version) {
if (device == NULL || version == NULL) {
if (amEepromDebugLevel > 0) amiDebugLog("PARAM Error.");
return AM_EEPROM_STATUS_ERR_INVALID_PARAM;
}
if (device->m_superio == INVALID_HANDLE_VALUE) {
if (amEepromDebugLevel > 0) amiDebugLog("Device not opened.");
return AM_EEPROM_STATUS_ERR_SYS;
}
DWORD bytesReturned;
DWORD buffer;
BOOL s = DeviceIoControl(device->m_superio, IOCTL_MXSMBUS_GET_VERSION, NULL, 0, &buffer, 4,
&bytesReturned, NULL);
if (s && bytesReturned == sizeof buffer) {
*version = buffer;
return AM_EEPROM_STATUS_OK;
}
if (amEepromDebugLevel > 0) amiDebugLog("DeviceIoControl error(%ld).", GetLastError());
return AM_EEPROM_STATUS_ERR_SYS;
}
AM_EEPROM_STATUS amEepromCreateMutex(AM_EEPROM *device) {
SECURITY_ATTRIBUTES muxAttrs;
SECURITY_DESCRIPTOR securityDescriptor;
SID_IDENTIFIER_AUTHORITY idAuth;
PSID *pSid = &device->m_sid;
idAuth.Value[0] = 0;
idAuth.Value[1] = 0;
idAuth.Value[2] = 0;
idAuth.Value[3] = 0;
idAuth.Value[4] = 0;
idAuth.Value[5] = 1;
if (!AllocateAndInitializeSid(&idAuth, 1, 0, 0, 0, 0, 0, 0, 0, 0, pSid)) {
if (amEepromDebugLevel > 0) amiDebugLog("AllocateAndInitializeSid Error in amEepromInit.");
*pSid = NULL;
goto amEepromCreateMutexError;
}
if (!InitializeSecurityDescriptor(&securityDescriptor, 1)) {
if (amEepromDebugLevel > 0)
amiDebugLog("InitializeSecurityDescriptor Error in amEepromInit.");
goto amEepromCreateMutexError;
}
if (!SetSecurityDescriptorDacl(&securityDescriptor, TRUE, NULL, FALSE)) {
if (amEepromDebugLevel > 0) amiDebugLog("SetSecurityDescriptorDacl Error in amEepromInit.");
goto amEepromCreateMutexError;
}
muxAttrs.lpSecurityDescriptor = &securityDescriptor;
muxAttrs.nLength = 12;
muxAttrs.bInheritHandle = FALSE;
if ((device->m_mutex = CreateMutexA(&muxAttrs, FALSE, "Global\\AM_EEPROM_MUTEX")) != NULL) {
return AM_EEPROM_STATUS_OK;
}
if (amEepromDebugLevel > 0) amiDebugLog("CreateMutexA Error(%ld).", GetLastError());
amEepromCreateMutexError:
if (device->m_mutex != NULL) {
CloseHandle(device->m_mutex);
device->m_mutex = NULL;
}
if (*pSid != NULL) {
FreeSid(*pSid);
*pSid = NULL;
}
return AM_EEPROM_STATUS_ERR_SYS;
}
AM_EEPROM_STATUS amEepromInit(AM_EEPROM_TIMEOUT *timeout) {
if (amEeprom.m_init) return AM_EEPROM_STATUS_ERR_ALREADY_INIT;
amEeprom.m_prt = AM_EEPROM_ADDR;
amEeprom.m_timeout.ReadTimeout = AM_EEPROM_DEFAULT_TIMEOUT;
amEeprom.m_timeout.WriteTimeout = AM_EEPROM_DEFAULT_TIMEOUT;
int ret = amEepromCreateMutex(&amEeprom);
if (ret != 0) {
if (amEepromDebugLevel > 0)
amiDebugLog("amEepromCreateMutex Error!! Error Code is %ld!!", ret);
ret = AM_EEPROM_STATUS_ERR_SYS;
goto amEepromInitError;
}
if (ret != 0) {
if (amEepromDebugLevel > 0)
amiDebugLog("amEepromCreateMutex Error!! Error Code is %ld!!", ret);
ret = AM_EEPROM_STATUS_ERR_SYS;
goto amEepromInitError;
}
amEeprom.m_superio = amEepromCreateDeviceFile(&MXSMBUS_GUID, 0, 0);
if (amEeprom.m_superio == INVALID_HANDLE_VALUE) {
if (amEepromDebugLevel > 0) amiDebugLog("amEepromCreateDeviceFile Error in amEepromInit.");
ret = AM_EEPROM_STATUS_ERR_SYS;
goto amEepromInitError;
}
DWORD driverVersion;
ret = amEepromGetDriverVersion(&amEeprom, &driverVersion);
if (ret != 0) {
amiDebugLog("amEepromGetDriverVerision Error.");
goto amEepromInitError;
}
if ((driverVersion & 0xffff) != 1) {
if (amEepromDebugLevel > 0)
amiDebugLog(
"Unknown SMBUS Driver Protocol(0x%08x). Please update SMBUS driver or user "
"program.",
driverVersion);
ret = AM_EEPROM_STATUS_ERR_PROTOCOL_VER;
goto amEepromInitError;
}
if (timeout != NULL) {
amEeprom.m_timeout.ReadTimeout = timeout->ReadTimeout;
amEeprom.m_timeout.WriteTimeout = timeout->WriteTimeout;
}
amEeprom.m_init = TRUE;
return AM_EEPROM_STATUS_OK;
amEepromInitError:
amEeprom.m_init = TRUE;
amEepromExit();
return ret;
}
AM_EEPROM_STATUS amEepromExit() {
if (!amEeprom.m_init) {
if (amEepromDebugLevel > 0) amiDebugLog("No Init Error!!");
return AM_EEPROM_STATUS_ERR_NO_INIT;
}
if (amEeprom.m_superio != INVALID_HANDLE_VALUE) {
CloseHandle(amEeprom.m_superio);
amEeprom.m_superio = INVALID_HANDLE_VALUE;
}
if (amEeprom.m_mutex != NULL) {
CloseHandle(amEeprom.m_mutex);
amEeprom.m_mutex = NULL;
}
if (amEeprom.m_sid != NULL) {
FreeSid(amEeprom.m_sid);
amEeprom.m_sid = NULL;
}
amEeprom.m_init = FALSE;
return AM_EEPROM_STATUS_OK;
}
BOOL amEepromI2CReadBlock(AM_EEPROM *device, WORD reg, BYTE nBytes, LPBYTE buffer) {
if (device == NULL || buffer == NULL || nBytes == 0 || nBytes >= 0x21) {
return false;
}
MXSMBUS_I2C_PACKET packet;
packet.v_addr = device->m_prt;
packet.command_code = reg;
packet.status = 0;
packet.command = MXSMBUS_CMD_READ_BLOCK;
packet.nbytes = nBytes;
DWORD bytesReturned;
BOOL s = DeviceIoControl(device->m_superio, IOCTL_MXSMBUS_I2C, &packet, sizeof packet, &packet,
sizeof packet, &bytesReturned, NULL);
if (!s || bytesReturned != sizeof packet) {
return false;
}
if (packet.status != 0) {
if (amEepromDebugLevel > 0)
amiDebugLog(" .. SMBus read error. prt=0x%02x addr=0x%02x reg=0x%04x", packet.command,
packet.v_addr, packet.command_code);
return false;
}
memcpy(buffer, packet.data, nBytes);
return true;
}
BOOL amEepromI2CWriteBlock(AM_EEPROM *device, WORD reg, BYTE nBytes, LPBYTE buffer) {
if (device == NULL || buffer == NULL || nBytes == 0 || nBytes >= 0x21) {
return false;
}
MXSMBUS_I2C_PACKET packet;
packet.v_addr = device->m_prt;
packet.command_code = reg;
packet.status = 0;
packet.command = MXSMBUS_CMD_WRITE_BLOCK;
packet.nbytes = nBytes;
memcpy(packet.data, buffer, nBytes);
DWORD bytesReturned;
BOOL s = DeviceIoControl(device->m_superio, IOCTL_MXSMBUS_I2C, &packet, sizeof packet, &packet,
sizeof packet, &bytesReturned, NULL);
if (!s || bytesReturned != sizeof packet) {
return false;
}
if (packet.status != 0) {
if (amEepromDebugLevel > 0)
amiDebugLog(" .. SMBus write error. status=0x%02x, prt=0x%02x addr=0x%02x reg=0x%04x\n",
packet.status, packet.command, packet.v_addr, packet.command_code);
return false;
}
return true;
}
BOOL amiEepromWait(AM_EEPROM *device, int timeout) {
amtime_t startTime;
amtime_t nowTime;
if (device == NULL) return FALSE;
MXSMBUS_REQUEST_PACKET packet;
packet.status = 24;
packet.command = MXSMBUS_CMD_READ_BYTE;
packet.v_addr = device->m_prt;
packet.command_code = 0;
packet.nbytes = 0;
packet.data[0] = 0;
packet.data[1] = 0;
amiTimerGet(&startTime);
while (1) {
amiTimerGet(&nowTime);
DWORD bytesReturned;
DeviceIoControl(device->m_superio, IOCTL_MXSMBUS_REQUEST, &packet, sizeof packet, &packet,
sizeof packet, &bytesReturned, NULL);
if (packet.status == 0) return TRUE;
if (amiTimerDiffUsec(&startTime, &nowTime) > timeout * 1000) return FALSE;
}
}
AM_EEPROM_STATUS amEepromRead(WORD reg, LPBYTE buf, DWORD length) {
if (amEeprom.m_init == 0) {
if (amEepromDebugLevel > 0) amiDebugLog("No Init Error.");
return AM_EEPROM_STATUS_ERR_NO_INIT;
}
if (buf == NULL || length == 0) return AM_EEPROM_STATUS_ERR_INVALID_PARAM;
DWORD err = WaitForSingleObject(amEeprom.m_mutex, 256);
if (err == WAIT_FAILED) {
if (amEepromDebugLevel > 0) amiDebugLog("WaitForSingleObject Error(%ld).", GetLastError());
return AM_EEPROM_STATUS_ERR_SYS;
}
if (err == WAIT_TIMEOUT) return AM_EEPROM_STATUS_ERR_GET_MUTEX;
if (!(err == WAIT_OBJECT_0 || err == WAIT_ABANDONED)) {
if (amEepromDebugLevel > 0)
amiDebugLog("WaitForSingleObject Error(%ld). Return Value is %d.", GetLastError(), err);
return AM_EEPROM_STATUS_ERR_SYS;
}
while (length != 0) {
BYTE readSize = 0x20;
if ((reg & 0x1f) != 0) readSize = 0x20 - (reg & 0x1f);
if (length <= readSize) readSize = length & 0xff;
if (!amiEepromWait(&amEeprom, amEeprom.m_timeout.ReadTimeout))
return AM_EEPROM_STATUS_ERR_TIMEOUT;
if (!amEepromI2CReadBlock(&amEeprom, reg, readSize, buf)) return AM_EEPROM_STATUS_ERR_READ;
buf += readSize;
reg += readSize;
length -= readSize;
}
if (!ReleaseMutex(amEeprom.m_mutex)) {
if (amEepromDebugLevel > 0) amiDebugLog("ReleaseMutex Error(%ld).", GetLastError());
return AM_EEPROM_STATUS_ERR_SYS;
}
return AM_EEPROM_STATUS_OK;
}
AM_EEPROM_STATUS amEepromWrite(WORD reg, LPBYTE buf, DWORD length) {
if (amEeprom.m_init == 0) {
if (amEepromDebugLevel > 0) amiDebugLog("No Init Error.");
return AM_EEPROM_STATUS_ERR_NO_INIT;
}
if (buf == NULL || length == 0) return AM_EEPROM_STATUS_ERR_INVALID_PARAM;
DWORD err = WaitForSingleObject(amEeprom.m_mutex, 256);
if (err == WAIT_FAILED) {
if (amEepromDebugLevel > 0) amiDebugLog("WaitForSingleObject Error(%ld).", GetLastError());
return AM_EEPROM_STATUS_ERR_SYS;
}
if (err == WAIT_TIMEOUT) return AM_EEPROM_STATUS_ERR_GET_MUTEX;
if (!(err == WAIT_OBJECT_0 || err == WAIT_ABANDONED)) {
if (amEepromDebugLevel > 0)
amiDebugLog("WaitForSingleObject Error(%ld). Return Value is %d.", GetLastError(), err);
return AM_EEPROM_STATUS_ERR_SYS;
}
while (length != 0) {
BYTE writeSize = 0x20;
if ((reg & 0x1f) != 0) writeSize = 0x20 - (reg & 0x1f);
if (length <= writeSize) writeSize = length & 0xff;
if (!amiEepromWait(&amEeprom, amEeprom.m_timeout.WriteTimeout))
return AM_EEPROM_STATUS_ERR_TIMEOUT;
if (!amEepromI2CWriteBlock(&amEeprom, reg, writeSize, buf))
return AM_EEPROM_STATUS_ERR_WRITE;
buf += writeSize;
reg += writeSize;
length -= writeSize;
}
if (!ReleaseMutex(amEeprom.m_mutex)) {
if (amEepromDebugLevel > 0) amiDebugLog("ReleaseMutex Error(%ld).", GetLastError());
return AM_EEPROM_STATUS_ERR_SYS;
}
return AM_EEPROM_STATUS_OK;
}