| /* |
| * 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 ¤tState){ |
| if(!isInitialized()){ |
| return false; |
| } |
| if (m_close_state == 2) |
| Open(); |
| if (!IoctlDev.IsOpened()) |
| return -1; |
| |
| GET_MODE_CMD_OUTPUT currentModeBuffer; |
| memset(¤tModeBuffer, 0, sizeof(GET_MODE_CMD_OUTPUT)); |
| |
| |
| lastError = IoctlDev.Ioctl(WILOCITY_IOCTL_GET_MODE_NEW, NULL, 0, ¤tModeBuffer, 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; |
| } |