blob: 3f1d1d48bdb2ca2b219cbdaa3964be4c13109199 [file] [log] [blame]
/*
* Copyright (c) 2017, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "wlct_os.h"
#include "PciDeviceAccess.h"
#include "WlctPciAcssHelper.h"
#include "DeviceAccess.h"
#include <ctime>
#include "Util.h"
//////////////////////////////////////////////////////////////////////////
// PCI interface
CPciDeviceAccess::CPciDeviceAccess(const TCHAR* tchDeviceName, DType devType)
: IoctlDev(tchDeviceName)/*, SamplingThread(SamplingThreadProc, this),
PciPluginThread(this)*/
{
LOG_MESSAGE_INFO(_T("Create PCI device access for: %s"), tchDeviceName);
_tcscpy_s(szInterfaceName, MAX_DEVICE_NAME_LEN, tchDeviceName);
deviceType = devType;
m_close_state = 2;
m_open_state = 0;
//LOG_MESSAGE_INFO(_T("[close %d] [open %d]"), m_close_state, m_open_state);
bInitialized = false;
Open();
if (bInitialized)
{
// PciPluginThread.Start();
}
return;
}
void CPciDeviceAccess::Open()
{
if (IoctlDev.IsOpened())
{
LOG_MESSAGE_INFO(_T("Already open. changing m_close_state = 0 and m_open_state = 2 [close %d] [open %d]"), m_close_state, m_open_state);
bInitialized = true;
m_close_state = 0;
m_open_state = 2;
return;
}
m_sampling_arr = NULL;
m_get_sampling_arr = NULL;
// m_hMonitorwPciPluginThread = NULL;
lastError = WLCT_OS_ERROR_SUCCESS;
dwBaseAddress = 0x880000;
bIsLocal = true;
TCHAR LorR = szInterfaceName[_tcslen(szInterfaceName) - 1];
if (LorR == _T('R') || LorR == _T('r'))
{
bIsLocal = false;
dwBaseAddress += 0x100000;
}
lastError = IoctlDev.Open();
if (lastError != WLCT_OS_ERROR_SUCCESS)
{
//LOG_MESSAGE_ERROR(_T("PCIdeviceAccess: failed to open driver wPci. ERROR_FILE_NOT_FOUND = %d"), lastError);
return;
}
// ReOpen();
bInitialized = true;
// LOG_MESSAGE_INFO(_T("changing m_close_state to 0 and m_open_state to 2 [close %d] [open %d]"), m_close_state, m_open_state);
m_close_state = 0;
m_open_state = 2;
m_flag_busy = false;
}
CPciDeviceAccess::~CPciDeviceAccess()
{
CloseDevice();
}
int CPciDeviceAccess::ReOpen()
{
LOG_MESSAGE_INFO(_T("Sending ioctl IOCTL_FILTER_OPEN_DEVICE"));
FILTER_OPEN_DEVICE openDevice;
lastError = IoctlDev.Ioctl(bIsLocal?IOCTL_FILTER_OPEN_LOCAL_DEVICE:IOCTL_FILTER_OPEN_REMOTE_DEVICE,
NULL, 0, &openDevice, sizeof(openDevice));
if ( lastError != WLCT_OS_ERROR_SUCCESS )
{
LOG_MESSAGE_ERROR(_T("Error in DeviceIoControl: IOCTL_FILTER_OPEN_DEVICE [err %d]"), lastError);
return -1;
}
LOG_MESSAGE_INFO(_T("Successfully sent ioctl IOCTL_FILTER_OPEN_DEVICE"));
return 0;
}
int CPciDeviceAccess::GetType()
{
return IDeviceAccess::ETypePCI;
}
int CPciDeviceAccess::InternalCloseDevice()
{
// DWORD bytesReturned = 0;
// sleep_ms(100);
// if (bIsLocal)
// {
// bRc = DeviceIoControl (hPciCtrlDevice, IOCTL_FILTER_CLOSE_LOCAL_DEVICE, NULL, 0, NULL, 0, &bytesReturned, NULL);
// }
// else
// {
// bRc = DeviceIoControl (hPciCtrlDevice, IOCTL_FILTER_CLOSE_REMOTE_DEVICE, NULL, 0, NULL, 0, &bytesReturned, NULL);
// }
// lastError = ::GetLastError();
// if ( !bRc || bytesReturned != 0)
// {
// LOG_MESSAGE_WARN(_T("Error in DeviceIoControl : %d"), lastError);
// }
// else
// {
// LOG_MESSAGE_INFO(_T("Successfully sent ioctl IOCTL_FILTER_CLOSE_DEVICE"))
// }
IoctlDev.Close();
// LOG_MESSAGE_INFO(_T("changing m_close_state to 2 [close %d] [open %d]"), m_close_state, m_open_state);
m_close_state = 2;
return 0;
}
int CPciDeviceAccess::CloseDevice()
{
//PciPluginThread.Stop();
if (InternalCloseDevice() == 0)
{
bInitialized = false;
//LOG_MESSAGE_INFO(_T("changing m_open_state to 0 and bInitialized to false [close %d] [open %d]"), m_close_state, m_open_state);
m_open_state = 0;
}
return 0;
}
#ifdef _WINDOWS
int CPciDeviceAccess::SetDriverMode(int newState, int &oldState, int &payloadResult)
{
if(!isInitialized()){
return -1;
}
if (m_close_state == 2)
Open();
if (!IoctlDev.IsOpened())
return -1;
SET_MODE_CMD_INPUT inBuffer;
SET_MODE_CMD_OUTPUT outBuffer;
memset(&inBuffer, 0, sizeof(SET_MODE_CMD_INPUT));
memset(&outBuffer, 0, sizeof(SET_MODE_CMD_OUTPUT));
inBuffer.mode = (DRIVER_MODE)newState;
lastError = IoctlDev.Ioctl(WILOCITY_IOCTL_SET_MODE_NEW, &inBuffer, sizeof(inBuffer), &outBuffer, sizeof(outBuffer));
if (lastError != WLCT_OS_ERROR_SUCCESS)
{
LOG_MESSAGE_WARN(_T("WILOCITY_IOCTL_SET_MODE_NEW failed. %X"), lastError);
oldState = -1;
return -1;
payloadResult = -1;
}
if(!outBuffer.result){
LOG_MESSAGE_WARN(_T("WILOCITY_IOCTL_SET_MODE_NEW did not change the mode"));
}
payloadResult = outBuffer.result;
oldState = outBuffer.previousMode;
return 0;
}
int CPciDeviceAccess::GetDriverMode(int &currentState){
if(!isInitialized()){
return false;
}
if (m_close_state == 2)
Open();
if (!IoctlDev.IsOpened())
return -1;
GET_MODE_CMD_OUTPUT currentModeBuffer;
memset(&currentModeBuffer, 0, sizeof(GET_MODE_CMD_OUTPUT));
lastError = IoctlDev.Ioctl(WILOCITY_IOCTL_GET_MODE_NEW, NULL, 0, &currentModeBuffer, sizeof(currentModeBuffer));
if (lastError != WLCT_OS_ERROR_SUCCESS)
{
LOG_MESSAGE_WARN(_T("WILOCITY_IOCTL_GET_MODE_NEW failed. %X"), lastError);
return -1;
}
currentState = currentModeBuffer.currentMode;
return 0;
}
#endif //_WINDOWS
// MARLON
int CPciDeviceAccess::r32(DWORD addr, DWORD & val)
{
if (!isInitialized())
return -1;
if (m_close_state == 2)
Open();
if (!IoctlDev.IsOpened())
return -1;
FILTER_1_ULONG_PARAM inParams;
FILTER_1_ULONG_PARAM outParams;
inParams.param = addr;
if (!bIsLocal)
{
inParams.param += 0x100000;
}
if (IoctlDev.bOldIoctls)
lastError = IoctlDev.Ioctl(IOCTL_INDIRECT_READ_OLD, &inParams, sizeof(inParams), &outParams, sizeof(outParams));
else
lastError = IoctlDev.Ioctl(WILOCITY_IOCTL_INDIRECT_READ, &inParams, sizeof(inParams), &outParams, sizeof(outParams));
if (lastError != WLCT_OS_ERROR_SUCCESS)
{
LOG_MESSAGE_WARN(_T("WILOCITY_IOCTL_INDIRECT_READ failed. %X"), lastError);
return -1;
}
val = outParams.param;
LOG_MESSAGE_DEBUG(_T("ADDR(in bytes): 0x%X Value: 0x%X"), addr, val);
return 0;
}
bool CPciDeviceAccess::try2open(int timeout)
{
do
{
Open();
if (IoctlDev.IsOpened())
break;
sleep_ms(100);
timeout -= 100;
} while (timeout > 0);
if (!IoctlDev.IsOpened())
return false;
return true;
}
int CPciDeviceAccess::do_interface_reset()
{
if (!isInitialized())
return -1;
if (m_close_state == 2)
Open();
if (!IoctlDev.IsOpened())
return -1;
FILTER_1_ULONG_PARAM inParams;
FILTER_1_ULONG_PARAM outParams;
/*inParams.param = addr;
if (!bIsLocal)
{
inParams.param += 0x100000;
}*/
lastError = IoctlDev.Ioctl(WILOCITY_IOCTL_DEVICE_SW_RESET, &inParams, sizeof(inParams), &outParams, sizeof(outParams));
if (lastError != WLCT_OS_ERROR_SUCCESS)
{
LOG_MESSAGE_WARN(_T("WILOCITY_IOCTL_DEVICE_SW_RESET failed. %X"), lastError);
InternalCloseDevice();
return -1;
}
//val = outParams.param;
LOG_MESSAGE_INFO(_T("Pci Interface Reset using IOCTL"));
return 0;
}
int CPciDeviceAccess::do_sw_reset()
{
LOG_MESSAGE_ERROR(_T("NOT IMPLEMENTED"));
return WLCT_OS_ERROR_CALL_NOT_IMPLEMENTED;
}
#define USING_RESET_FUNCTION 0
int CPciDeviceAccess::do_reset(BOOL bFirstTime)
{
if (USING_RESET_FUNCTION == 0)
{
LOG_MESSAGE_WARN(_T("reset was not done because USING_RESET_FUNCTION == 0"));
return -1;
}
if (!isInitialized())
return -1;
if (m_close_state == 2)
Open();
if (!IoctlDev.IsOpened())
return -1;
DWORD addr;
if (deviceStep == STEP_NONE)
addr = 0x880AE0;
else if (deviceStep == MARLON_STEP_B0 || deviceStep == SPARROW_STEP_A0 || deviceStep == SPARROW_STEP_B0)
addr = 0x880B04;
else // default
{
addr = 0x880B04;
}
DWORD val;
bool bres;
// check if there is an access to the board
int ret = r32(BAUD_RATE_REGISTER, val);
if (ret != 0 || val == 0 || val == 0xFFFFFFFF)
{
// access failed.
if (bFirstTime == FALSE)
return -1;
// do disable enable
InternalCloseDevice();
sleep_ms(500);
bres = Util::ICHDisableEnable();
if (!bres)
sleep_ms(1000);
Open();
do_reset(FALSE);
}
w32(addr, 1);
InternalCloseDevice();
sleep_ms(500);
bres = Util::ICHDisableEnable();
bres = try2open(2000);
if (!bres)
{
LOG_MESSAGE_INFO(_T("do_reset: failed to open the device after reset"));
return -1;
}
int timeout = 2000;
bres = false;
do
{
ret = r32(BAUD_RATE_REGISTER, val);
if (ret == 0 && val > 0 && val < 0xFFFFFFFF)
{
bres = true;
break;
}
sleep_ms(100);
timeout -= 100;
} while (timeout > 0);
if (!bres)
{
LOG_MESSAGE_ERROR(_T("ERROR: failed to read the baudrate after reset."));
return -1;
}
return 0;
}
int CPciDeviceAccess::reset_complete()
{
DWORD val;
bool bres;
int ret;
InternalCloseDevice();
sleep_ms(500);
Util::ICHDisableEnable();
bres = try2open(2000);
if (!bres)
{
LOG_MESSAGE_INFO(_T("failed to open the device after reset"));
return -1;
}
int timeout = 2000;
bres = false;
do
{
ret = r32(BAUD_RATE_REGISTER, val);
if (ret == 0 && val > 0 && val < 0xFFFFFFFF)
{
bres = true;
break;
}
sleep_ms(100);
timeout -= 100;
} while (timeout > 0);
if (!bres)
{
LOG_MESSAGE_ERROR(_T("ERROR: failed to read the baudrate after reset."));
return -1;
}
return 0;
}
// marlon
int CPciDeviceAccess::w32(DWORD addr, DWORD val)
{
if (!isInitialized())
return -1;
if (m_close_state == 2)
Open();
if (!IoctlDev.IsOpened())
return -1;
FILTER_2_ULONG_PARAM inParams;
inParams.param1 = addr;
if (!bIsLocal)
{
inParams.param1 += 0x100000;
}
inParams.param2 = val;
if (IoctlDev.bOldIoctls)
lastError = IoctlDev.Ioctl(IOCTL_INDIRECT_WRITE_OLD, &inParams, sizeof(inParams), NULL, 0);
else
lastError = IoctlDev.Ioctl(WILOCITY_IOCTL_INDIRECT_WRITE, &inParams, sizeof(inParams), NULL, 0);
if (lastError != WLCT_OS_ERROR_SUCCESS)
{
LOG_MESSAGE_WARN(_T("IOCTL_INDIRECT_WRITE failed. %X"), lastError);
InternalCloseDevice();
return -1;
}
if (USING_RESET_FUNCTION == 0)
{
if (((deviceStep == STEP_NONE) && (addr == 0x880AE0)) || ((deviceStep == MARLON_STEP_B0 || deviceStep == SPARROW_STEP_A0 || deviceStep == SPARROW_STEP_B0) && (addr == 0x880B04)))
{
if (val & 0x1)
{
LOG_MESSAGE_WARN(_T("Calling reset from write command instead of calling reset directly!!!!!!!!!!!!!!!!!!!!!!!!!!"));
reset_complete();
}
}
}
LOG_MESSAGE_DEBUG(_T("ADDR: 0x%X Value: 0x%X"),addr, val);
return 0;
}
// addr is in bytes.
// block size for SWITH is number of 16 bits and MARLON is number of bytes
// In MARLON the block size should be align to 32 bits (otherwise it will be
// truncated by the hardware)
//
int CPciDeviceAccess::rb(DWORD addr, DWORD blockSize, char *arrBlock)
{
if (!isInitialized())
return -1;
// if (m_close_state == 1)
// InternalCloseDevice();
// if (m_open_state == 1)
// Open();
// if (m_close_state == 2)
// return -1;
if (m_close_state == 2)
Open();
if (!IoctlDev.IsOpened())
return -1;
//if (GetDeviceType() == MST_MARLON)
//{
FILTER_1_ULONG_PARAM inParams;
inParams.param = addr;
if (!bIsLocal)
{
inParams.param += 0x100000;
}
if (IoctlDev.bOldIoctls)
lastError = IoctlDev.Ioctl(IOCTL_INDIRECT_READ_BLOCK, &inParams, sizeof(inParams), arrBlock, blockSize);
else
lastError = IoctlDev.Ioctl(WILOCITY_IOCTL_INDIRECT_READ_BLOCK, &inParams, sizeof(inParams), arrBlock, blockSize);
// DWORD le = GetLastError();
// LOG_MESSAGE_WARN(_T("IOCTL_INDIRECT_READ return %d [lastError 0x%X]"), bRc, le);
if (lastError != WLCT_OS_ERROR_SUCCESS)
{
LOG_MESSAGE_WARN(_T("IOCTL_INDIRECT_READ failed. %X"), lastError);
InternalCloseDevice();
return -1;
}
//}
return 0;
}
int CPciDeviceAccess::wb(DWORD addr, DWORD blockSize, const char *arrBlock)
{
if (!isInitialized())
return -1;
if (m_close_state == 2)
Open();
if (!IoctlDev.IsOpened())
return -1;
PFILTER_WRITE_BLOCK pinParams;
char* p = new char[2*sizeof(ULONG) + blockSize];
if (!p) return -1;
pinParams = (PFILTER_WRITE_BLOCK)p;
pinParams->address = addr;
if (!bIsLocal)
{
pinParams->address += 0x100000;
}
pinParams->size = blockSize;
memcpy(pinParams->buffer, arrBlock, blockSize);
if (IoctlDev.bOldIoctls)
lastError = IoctlDev.Ioctl(IOCTL_INDIRECT_WRITE_BLOCK, pinParams, 2*sizeof(ULONG) + blockSize, NULL, 0);
else
lastError = IoctlDev.Ioctl(WILOCITY_IOCTL_INDIRECT_WRITE_BLOCK, pinParams, 2*sizeof(ULONG) + blockSize, NULL, 0);
if (lastError != WLCT_OS_ERROR_SUCCESS)
{
LOG_MESSAGE_WARN(_T("WILOCITY_IOCTL_INDIRECT_WRITE_BLOCK failed. %X"), lastError);
InternalCloseDevice();
delete [] p;
return -1;
}
delete [] p;
return 0;
}
void CPciDeviceAccess::rr32(DWORD addr, DWORD num_repeat, DWORD *arrBlock)
{
WLCT_UNREFERENCED_PARAM(addr);
WLCT_UNREFERENCED_PARAM(num_repeat);
WLCT_UNREFERENCED_PARAM(arrBlock);
WLCT_ASSERT(0);
}
int CPciDeviceAccess::rr(DWORD addr, DWORD num_repeat, DWORD *arrBlock)
{
if (!isInitialized())
return -1;
if (m_close_state == 2)
Open();
if (!IoctlDev.IsOpened())
return -1;
//if (GetDeviceType() == MST_MARLON)
//{
FILTER_1_ULONG_PARAM inParams;
inParams.param = addr;
if (!bIsLocal)
{
inParams.param += 0x100000;
}
lastError = IoctlDev.Ioctl(IOCTL_INDIRECT_READ_REPEAT, &inParams, sizeof(inParams), arrBlock, num_repeat*sizeof(DWORD));
if (lastError != WLCT_OS_ERROR_SUCCESS)
{
LOG_MESSAGE_WARN(_T("IOCTL_INDIRECT_READ failed. %X"), lastError);
InternalCloseDevice();
return -1;
}
// actualAddr = addr - dwBaseAddress;
// if (actualAddr >= CRSsize)
// return -1;
//
// rr32(actualAddr>>2, num_repeat, arrBlock);
//}
return 0;
}
int CPciDeviceAccess::getFwDbgMsg(FW_DBG_MSG** pMsg)
{
(void)pMsg;
// LOG_MESSAGE_DEBUG(_T("NOT IMPLEMENTED"));
return WLCT_OS_ERROR_CALL_NOT_IMPLEMENTED;
}
int CPciDeviceAccess::clearAllFwDbgMsg()
{
LOG_MESSAGE_ERROR(_T("NOT IMPLEMENTED"));
return WLCT_OS_ERROR_CALL_NOT_IMPLEMENTED;
}
/*
void CPciDeviceAccess::SamplingThreadProc(void *pDeviceAccss)
{
LOG_MESSAGE_DEBUG(_T("start running"));
CPciDeviceAccess *pDevice = (CPciDeviceAccess*)pDeviceAccss;
#ifdef WCLT_SAMPLING_TO_FILE_IS_SUPPORTED
HANDLE hSamplingFile = INVALID_HANDLE_VALUE;
#endif
uint64_t startTS;
pDevice->m_sampling_head = 0;
pDevice->m_sampling_tail = 0;
pDevice->m_loops = 0;
startTS = GetTimeStampMs();
WLCT_UNREFERENCED_PARAM(startTS);
SAMPLING_REGS* currEntry;
#ifdef WCLT_SAMPLING_TO_FILE_IS_SUPPORTED
DWORD written = 0;
if (pDevice->m_transferMethod == 1)
{ // saving to file
TCHAR file_name[256];
_stprintf (file_name, _T("c:\\sampling_%X.bin"), GetTickCount());
hSamplingFile = CreateFile(file_name, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hSamplingFile == INVALID_HANDLE_VALUE)
{
return;
}
// first data in the file is the number of registers in each sampling
WriteFile(hSamplingFile, &pDevice->m_no_sampling_regs, sizeof(pDevice->m_no_sampling_regs), &written, NULL);
// then write the registers address
WriteFile(hSamplingFile, pDevice->m_pRegsArr, sizeof(DWORD)* pDevice->m_no_sampling_regs, &written, NULL);
}
#endif
uint64_t last_timeStamp = 0;
do
{
//sleep_ms(pDevice->m_interval);
do
{
sleep_ms(0);
} while ( (GetTimeStampMs() - last_timeStamp) < pDevice->m_interval);
last_timeStamp = GetTimeStampMs();
currEntry = (SAMPLING_REGS*)(pDevice->m_sampling_arr + pDevice->m_sampling_head * (pDevice->m_no_sampling_regs + 1));
currEntry->timeStamp = (DWORD)last_timeStamp;
for (DWORD i = 0; i < pDevice->m_no_sampling_regs; i++)
{
DWORD val;
if (pDevice->GetDeviceType() == MST_SWIFT)
{
pDevice->r2(pDevice->m_pRegsArr[i], val);
currEntry->regArr[i] = val;
}
else if (pDevice->GetDeviceType() == MST_MARLON)
{
pDevice->r32(pDevice->m_pRegsArr[i], currEntry->regArr[i]);
}
}
pDevice->m_sampling_head++;
if (pDevice->m_sampling_head >= pDevice->m_maxSampling)
{
pDevice->m_sampling_head = 0;
#ifdef WCLT_SAMPLING_TO_FILE_IS_SUPPORTED
if (pDevice->m_transferMethod == 1)
{
// save the buffer to the disk;
WriteFile(hSamplingFile, pDevice->m_sampling_arr, pDevice->oneSamplingSize * pDevice->m_maxSampling, &written, NULL);
}
#endif
if (pDevice->m_transferMethod == 2)
{
pDevice->m_loops++;
}
}
} while (!pDevice->SamplingThread.ShouldStop());
#ifdef WCLT_SAMPLING_TO_FILE_IS_SUPPORTED
if (pDevice->m_transferMethod == 1)
{
CloseHandle(hSamplingFile);
}
#endif
LOG_MESSAGE_DEBUG(_T("Leaving"));
}
int CPciDeviceAccess::startSampling(
DWORD* pRegsArr,
DWORD regArrSize,
DWORD interval,
DWORD maxSampling,
DWORD transferMethod)
{
m_no_sampling_regs = regArrSize;
m_pRegsArr = new DWORD[regArrSize];
memcpy(m_pRegsArr, pRegsArr, sizeof(DWORD)*regArrSize);
m_interval = interval;
m_maxSampling = maxSampling;
m_transferMethod = transferMethod;
// allocate the sampling buffer
// each sampling required:
// m_no_sampling_regs * sizeof(DWORD) + timestamp
oneSamplingSize = m_no_sampling_regs * sizeof(DWORD) + sizeof(DWORD);
m_sampling_arr = new DWORD[oneSamplingSize * m_maxSampling];
m_get_sampling_arr = new DWORD[oneSamplingSize * m_maxSampling];
// start the read tread
SamplingThread.Start();
sleep_ms(100);
return 0;
}
int CPciDeviceAccess::stopSampling()
{
SamplingThread.Stop();
// free the sampling buffers
delete [] m_pRegsArr;
delete [] m_sampling_arr;
delete [] m_get_sampling_arr;
return 0;
}
int CPciDeviceAccess::getSamplingData(DWORD** pDataSamples)
{
DWORD total_copy = 0;
// get the head and tail position
DWORD head = m_sampling_head;
DWORD tail = m_sampling_tail;
LOG_MESSAGE_DEBUG(_T("[head %X] [tail %X] [loops %d]"), head, tail, m_loops);
memset(m_get_sampling_arr, 0, oneSamplingSize * m_maxSampling);
// 0 - no new data. nothing to copy
// -1 - error
// 1 - copy from tail to head
// 2 - copy from tail to end buffer and then from start buffer to head
// 3 - overlapped. copy from head to head.
//
DWORD copy_type = 0;
if (m_loops == 0)
{
if (head == tail)
{
// no new data
copy_type = 0;
}
else if (head > tail)
{
// new data. copy from tail to head
copy_type = 1;
}
else if (head < tail)
{
// error
LOG_MESSAGE_ERROR(_T("ERROR: !!!!!!!! loop is ZERO [head %X] [tail %X]"), head, tail);
copy_type = -1;
}
}
else if (m_loops == 1)
{
if (head == tail)
{
// overlapped. copy head to head
copy_type = 3;
}
else if (head > tail)
{
// overlapped. copy head to head
copy_type = 3;
}
else if (head < tail)
{
// copy from tail to end buffer and then from start buffer to head
copy_type = 2;
}
}
else if (m_loops > 1)
{
// overlapped. copy head to head
copy_type = 3;
}
DWORD srcPos;
switch (copy_type)
{
case 1:
{
srcPos = oneSamplingSize * tail / sizeof(DWORD);
memcpy(m_get_sampling_arr, &(m_sampling_arr[srcPos]), oneSamplingSize * (head - tail));
total_copy = oneSamplingSize * (head - tail);
}
break;
case 2:
{
// copy from tail to the end of the buffer
srcPos = oneSamplingSize * tail / sizeof(DWORD);
memcpy(m_get_sampling_arr, &(m_sampling_arr[srcPos]), oneSamplingSize * (m_maxSampling - tail));
//
DWORD nextIndex = (oneSamplingSize * (m_maxSampling - tail))/sizeof(DWORD);
memcpy(&(m_get_sampling_arr[nextIndex]), m_sampling_arr, oneSamplingSize * head);
total_copy = oneSamplingSize * (m_maxSampling - tail) + oneSamplingSize * head;
}
break;
case 3:
{
// copy all the cyclic buffer, starting from the head
// the head is pointing to the next place to put there new sample.
// there is a racing condition because it is possible that just before
// we will start coping a context switch will happened and the read
// sampling thread will overwrite this area.
// we are not locking this sharing resource for now
memcpy(m_get_sampling_arr, &(m_sampling_arr[head]), oneSamplingSize * (m_maxSampling - head));
// copy from the beginning till the head
DWORD nextIndex = (oneSamplingSize * (m_maxSampling - head))/sizeof(DWORD);
memcpy(&(m_get_sampling_arr[nextIndex]), &(m_sampling_arr[0]), oneSamplingSize * head);
total_copy = oneSamplingSize * m_maxSampling;
LOG_MESSAGE_WARN(_T("detect a loop [%d]. samples lost."), m_loops);
}
break;
}
m_loops = 0;
m_sampling_tail = head;
LOG_MESSAGE_DEBUG(_T("[m_sampling_tail %X] [total_copy %d]"), m_sampling_tail, total_copy);
*pDataSamples = m_get_sampling_arr;
return total_copy;
}
*/
int CPciDeviceAccess::alloc_pmc(int num_of_descriptors, int size_of_descriptor){
if (!isInitialized())
{
LOG_MESSAGE_ERROR(_T("alloc_pmc - Not initialized"));
return -1;
}
if (m_close_state == 2)
{
Open();
}
if (!IoctlDev.IsOpened())
{
LOG_MESSAGE_ERROR(_T("alloc_pmc - Not opened"));
return -1;
}
int data[2] = {num_of_descriptors, size_of_descriptor};
int res = IoctlDev.DebugFS((char*)"pmccfg", data, 8, 0);
if (res != WLCT_OS_ERROR_SUCCESS)
{
LOG_MESSAGE_ERROR(_T("Cannot open DebugFS for pmccfg: 0x%X"), res);
}
return res;
}
#ifdef _WINDOWS
int CPciDeviceAccess::send_wmi_cmd(SEND_RECEIVE_WMI* wmi)
{
LOG_MESSAGE_INFO(_T("send_wmi_cmd: 0x%X"), wmi->uCmdId);
if (!isInitialized())
return -1;
lastError = IoctlDev.Ioctl(WILOCITY_IOCTL_SEND_WMI, wmi, sizeof(SEND_RECEIVE_WMI), NULL, 0);
if (lastError != WLCT_OS_ERROR_SUCCESS)
{
LOG_MESSAGE_WARN(_T("WILOCITY_IOCTL_SEND_WMI failed. %X"), lastError);
return lastError;
}
return 0;
}
int CPciDeviceAccess::recieve_wmi_event(SEND_RECEIVE_WMI* evt)
{
LOG_MESSAGE_INFO(_T("recieve_wmi_event"));
if (!isInitialized())
return -1;
lastError = IoctlDev.Ioctl( WILOCITY_IOCTL_RECEIVE_WMI, NULL, 0, evt, sizeof(SEND_RECEIVE_WMI));
if (lastError != WLCT_OS_ERROR_SUCCESS)
{
LOG_MESSAGE_WARN(_T("WILOCITY_IOCTL_RECEIVE_WMI failed. %X"), lastError);
return lastError;
}
return 0;
}
#endif //_WINDOWS
int CPciDeviceAccess::register_driver_mailbox_event(HANDLE* pMailboxEventHandle )
{
LOG_MESSAGE_INFO(_T("register_driver_mailbox_event"));
if (!isInitialized())
return -1;
if (!IoctlDev.IsOpened())
return -1;
REGISTER_EVENT req;
memset(&req, 0, sizeof(REGISTER_EVENT));
req.hEvent = *pMailboxEventHandle;
lastError = IoctlDev.Ioctl(WILOCITY_IOCTL_REGISTER_WMI_RX_EVENT, &req, sizeof(REGISTER_EVENT), NULL, 0);
if (lastError != WLCT_OS_ERROR_SUCCESS)
{
LOG_MESSAGE_WARN(_T("WILOCITY_IOCTL_REGISTER_WMI_RX_EVENT failed. 0x%X"), lastError);
InternalCloseDevice();
return -1;
}
return ERROR_SUCCESS;
}
int CPciDeviceAccess::register_device_unplug2(INT_PTR hEvent){
LOG_MESSAGE_INFO(_T("register_device_unplug2"));
WLCT_UNREFERENCED_PARAM(hEvent);
if (!isInitialized())
return -1;
if (!IoctlDev.IsOpened())
return -1;
#ifdef _WINDOWS
DRIVER_REGISTER_EVENT req;
memset(&req, 0, sizeof(DRIVER_REGISTER_EVENT));
LOG_MESSAGE_INFO(_T("register_device_unplug2: <Event Pointer=0x%p>"), hEvent);
req.UserEventHandle = hEvent;
lastError = IoctlDev.Ioctl( WILOCITY_IOCTL_REGISTER_DEVICE, &req, sizeof(req), NULL, 0);
#endif //_WINDOWS
if (lastError != WLCT_OS_ERROR_SUCCESS)
{
LOG_MESSAGE_WARN(_T("register_device_unplug2 failed. 0x%X"), lastError);
InternalCloseDevice();
return -1;
}
return ERROR_SUCCESS;
}
int CPciDeviceAccess::unregister_device_unplug2(){
LOG_MESSAGE_INFO(_T("unregister_device_unplug2"));
if (!isInitialized())
return -1;
if (!IoctlDev.IsOpened())
return -1;
#ifdef _WINDOWS
DRIVER_REGISTER_EVENT req;
memset(&req, 0, sizeof(DRIVER_REGISTER_EVENT));
LONG invalidPointer = -1;
LOG_MESSAGE_INFO(_T("register_device_unplug2: <Event Pointer=0x%X>"), invalidPointer);
req.UserEventHandle = invalidPointer;
lastError = IoctlDev.Ioctl( WILOCITY_IOCTL_REGISTER_DEVICE, &req, sizeof(req), NULL, 0);
#endif //_WINDOWS
if (lastError != WLCT_OS_ERROR_SUCCESS)
{
LOG_MESSAGE_WARN(_T("register_device_unplug2 failed. 0x%X"), lastError);
InternalCloseDevice();
return -1;
}
return ERROR_SUCCESS;
}
int CPciDeviceAccess::register_driver_device_event(INT_PTR hEvent,int deviceId, int eventId)
{
LOG_MESSAGE_INFO(_T("register_driver_device_event"));
WLCT_UNREFERENCED_PARAM(hEvent);
WLCT_UNREFERENCED_PARAM(deviceId);
WLCT_UNREFERENCED_PARAM(eventId);
if (!isInitialized())
return -1;
if (!IoctlDev.IsOpened())
return -1;
#ifdef _WINDOWS
LOG_MESSAGE_INFO(_T("register_driver_device_event: <Event Pointer=0x%p> <deviceId=0x%x> <EventId=0x%x>"), hEvent, deviceId, eventId);
// Our DLL assumed to be always compiled for 32bit application.
// Since the driver excpects to recieve HANDLEs of size that IS platform speciefic,
// we must dynamically find out if we are running on 64bit OS or now.
// for more information, read remarks on WlcyPciAcssWmi.h file
if (Util::Is64BitWindows())
{
LOG_MESSAGE_INFO(_T("register_driver_device_event Driver HANDLE problem WA, using 64bit struct"));
EVENT_HANDLE_64BIT req;
memset(&req, 0, sizeof(EVENT_HANDLE_64BIT));
req.DeviceId = deviceId;
req.EventId = eventId;
req.hEvent_l = hEvent;
req.hEvent_h = 0;
lastError = IoctlDev.Ioctl( WILOCITY_IOCTL_REGISTER_EVENT, &req, sizeof(req), NULL, 0);
}
else
{
LOG_MESSAGE_INFO(_T("register_driver_device_event Driver HANDLE problem WA, using 32bit struct"));
EVENT_HANDLE_32BIT req;
memset(&req, 0, sizeof(EVENT_HANDLE_32BIT));
req.DeviceId = deviceId;
req.EventId = eventId;
req.hEvent = hEvent;
lastError = IoctlDev.Ioctl( WILOCITY_IOCTL_REGISTER_EVENT, &req, sizeof(req), NULL, 0);
}
#endif //_WINDOWS
if (lastError != WLCT_OS_ERROR_SUCCESS)
{
LOG_MESSAGE_WARN(_T("WILOCITY_IOCTL_REGISTER_EVENT failed. 0x%X"), lastError);
InternalCloseDevice();
return -1;
}
//do something with params
(void)deviceId;
(void)eventId;
return ERROR_SUCCESS;
}
int CPciDeviceAccess::register_driver_device_events(INT_PTR hDnEvent, INT_PTR hUpEvent, INT_PTR hUnplugEvent, INT_PTR hSysAssertEvent)
{
LOG_MESSAGE_INFO(_T("register_driver_device_events"));
WLCT_UNREFERENCED_PARAM(hDnEvent);
WLCT_UNREFERENCED_PARAM(hUpEvent);
WLCT_UNREFERENCED_PARAM(hUnplugEvent);
WLCT_UNREFERENCED_PARAM(hSysAssertEvent);
if (!isInitialized())
return -1;
if (!IoctlDev.IsOpened())
return -1;
#ifdef _WINDOWS
LOG_MESSAGE_INFO(_T("register_driver_device_events: <hDnEvent=0x%p> <hUpEvent=0x%p> <hUnplugEvent=0x%p> <hSysAssertEvent=0x%p>"), hDnEvent, hUpEvent, hUnplugEvent, hSysAssertEvent );
// Our DLL assumed to be always compiled for 32bit application.
// Since the driver excpects to recieve HANDLEs of size that IS platform speciefic,
// we must dynamically find out if we are running on 64bit OS or now.
// for more information, read remarks on WlcyPciAcssWmi.h file
if (Util::Is64BitWindows())
{
LOG_MESSAGE_INFO(_T("register_driver_device_events Driver HANDLES problem WA, using 64bit struct"));
SHARED_EVENT_64BIT req;
memset(&req, 0, sizeof(SHARED_EVENT_64BIT));
req.hDnEvent_l = hDnEvent;
req.hDnEvent_h = 0;
req.hUpEvent_l = hUpEvent;
req.hUpEvent_h = 0;
req.unplugEvent_l = hUnplugEvent;
req.hUpEvent_h = 0;
req.sysAssertEvent_l = hSysAssertEvent;
req.sysAssertEvent_h = 0;
lastError = IoctlDev.Ioctl( IOCTL_OPEN_USER_MODE_EVENT, &req, sizeof(req), NULL, 0);
}
else
{
LOG_MESSAGE_INFO(_T("register_driver_device_events Driver HANDLES problem WA, using 32bit struct"));
SHARED_EVENT_32BIT req;
memset(&req, 0, sizeof(SHARED_EVENT_32BIT));
req.hDnEvent = hDnEvent;
req.hUpEvent = hUpEvent;
req.unplugEvent = hUnplugEvent;
req.sysAssertEvent = hSysAssertEvent;
lastError = IoctlDev.Ioctl( IOCTL_OPEN_USER_MODE_EVENT, &req, sizeof(req), NULL, 0);
}
#endif //_WINDOWS
if (lastError != WLCT_OS_ERROR_SUCCESS)
{
LOG_MESSAGE_WARN(_T("IOCTL_OPEN_USER_MODE_EVENT failed. 0x%X"), lastError);
InternalCloseDevice();
return -1;
}
return ERROR_SUCCESS;
}
int CPciDeviceAccess::unregister_driver_device_events()
{
LOG_MESSAGE_INFO(_T("unregister_driver_device_events"));
if (!isInitialized())
return -1;
if (!IoctlDev.IsOpened())
return -1;
#ifdef _WINDOWS
LOG_MESSAGE_INFO(_T("unregister_driver_device_events with invalid handles"));
// Our DLL assumed to be always compiled for 32bit application.
// Since the driver excpects to recieve HANDLEs of size that IS platform speciefic,
// we must dynamically find out if we are running on 64bit OS or now.
// for more information, read remarks on WlcyPciAcssWmi.h file
if (Util::Is64BitWindows())
{
LOG_MESSAGE_INFO(_T("register_driver_device_events Driver HANDLES problem WA, using 64bit struct"));
SHARED_EVENT_64BIT req;
memset(&req, 0, sizeof(SHARED_EVENT_64BIT));
req.hDnEvent_l = -1;
req.hDnEvent_h = -1;
req.hUpEvent_l = -1;
req.hUpEvent_h = -1;
req.unplugEvent_l = -1;
req.hUpEvent_h = -1;
req.sysAssertEvent_l = -1;
req.sysAssertEvent_h = -1;
lastError = IoctlDev.Ioctl( IOCTL_OPEN_USER_MODE_EVENT, &req, sizeof(req), NULL, 0);
}
else
{
LOG_MESSAGE_INFO(_T("register_driver_device_events Driver HANDLES problem WA, using 32bit struct"));
SHARED_EVENT_32BIT req;
memset(&req, 0, sizeof(SHARED_EVENT_32BIT));
req.hDnEvent = -1;
req.hUpEvent = -1;
req.unplugEvent = -1;
req.sysAssertEvent = -1;
lastError = IoctlDev.Ioctl( IOCTL_OPEN_USER_MODE_EVENT, &req, sizeof(req), NULL, 0);
}
#endif //_WINDOWS
if (lastError != WLCT_OS_ERROR_SUCCESS)
{
LOG_MESSAGE_WARN(_T("IOCTL_OPEN_USER_MODE_EVENT failed. 0x%X"), lastError);
InternalCloseDevice();
return -1;
}
return ERROR_SUCCESS;
}
int CPciDeviceAccess::setMpDriverLogLevels(ULONG logModulesEnableMsk, ULONG logModuleLevelsMsk[WILO_DRV_NUM_LOG_COMPS])
{
LOG_MESSAGE_INFO(_T("setMpDriverLogLevels"));
if (!isInitialized())
return -1;
if (!IoctlDev.IsOpened())
return -1;
DRIVER_LOGS_CFG req;
memset(&req, 0, sizeof(DRIVER_LOGS_CFG));
req.logModulesEnableMsk = logModulesEnableMsk;
memcpy( req.logModuleLevelsMsk, logModuleLevelsMsk, (WILO_DRV_NUM_LOG_COMPS*4)) ;
lastError = IoctlDev.Ioctl( WILOCITY_IOCTL_DRIVER_LOG_LEVELS_CFG, &req, sizeof(req), NULL, 0);
if (lastError != WLCT_OS_ERROR_SUCCESS)
{
LOG_MESSAGE_WARN(_T("WILOCITY_IOCTL_DRIVER_LOG_LEVELS_CFG failed. 0x%X"), lastError);
InternalCloseDevice();
return -1;
}
return ERROR_SUCCESS;
}