Files
2026-02-01 22:23:06 +08:00

506 lines
15 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include <QMutex>
#include <QMutexLocker>
#include <iostream>
#include <chrono>
#include "time.h"
#include <sstream>
#include <ctime>
#include <QString>
#include <QDebug>
#include <QSpinBox>
#include <Windows.h>
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <strsafe.h>
#include <stdint.h>
#include <SetupAPI.h>
#include <INITGUID.H>
#include <WinIoCtl.h>
#include "PcieFun.h"
#include <io.h>
#include <setupapi.h>
#include <cfgmgr32.h>
#include <QThread>
#include <QDateTime>
#include "./XDmaCommDef.h"
#define BigLittleSwap32(A) ((((int)(A) & 0xff000000) >> 24) | \
(((int)(A) & 0x00ff0000) >> 8) | \
(((int)(A) & 0x0000ff00) << 8) | \
(((int)(A) & 0x000000ff) << 24))
typedef unsigned int uint;
#pragma comment(lib, "setupapi.lib")
#define MAX_BYTES_PER_TRANSFER 0x800000
#define FPGA_DDR_START_ADDR 0x00000000
static HANDLE h_c2h0 = INVALID_HANDLE_VALUE;
static HANDLE h_h2c0 = INVALID_HANDLE_VALUE;
static HANDLE h_user = INVALID_HANDLE_VALUE;
static HANDLE h_control = INVALID_HANDLE_VALUE;
static DWORD user_start_en;
static char base_path[MAX_PATH + 1] = "";
static bool m_bIsCardOpen = false;
QMutex g_regControlMutex;
static int verbose_msg(const char* const fmt, ...)
{
int ret = 0;
va_list args;
if (1)
{
va_start(args, fmt);
ret = vprintf(fmt, args);
va_end(args);
}
return ret;
}
static BYTE* allocate_buffer(size_t size, size_t alignment)
{
if (size == 0)
{
size = 4;
}
if (alignment == 0)
{
SYSTEM_INFO sys_info;
GetSystemInfo(&sys_info);
alignment = sys_info.dwPageSize;
//printf("alignment = %d\n",alignment);
}
verbose_msg("Allocating host-side buffer of size %d, aligned to %d bytes\n", size, alignment);
return (BYTE*)_aligned_malloc(size, alignment);
}
int Pcie_GetDevices(GUID id, char** devpath)
{
size_t path_len = MAX_PATH + 1;
for (int i = 0; i < 4; i++)
{
devpath[i] = (char*)malloc(sizeof(char) * path_len);
memset(devpath[i], 0, MAX_PATH + 1);
}
SP_DEVICE_INTERFACE_DATA device_interface;
PSP_DEVICE_INTERFACE_DETAIL_DATA dev_detail;
DWORD index;
HDEVINFO device_info;
wchar_t tmp[256];
device_info = SetupDiGetClassDevs((LPGUID)&id, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
if (device_info == INVALID_HANDLE_VALUE)
{
// fprintf(stderr, "GetDevices INVALID_HANDLE_VALUE\n");
exit(-1);
}
device_interface.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
// enumerate through devices
for (index = 0; SetupDiEnumDeviceInterfaces(device_info, NULL, &id, index, &device_interface); ++index)
{
// get required buffer size
ULONG detailLength = 0;
if (!SetupDiGetDeviceInterfaceDetail(device_info, &device_interface, NULL, 0, &detailLength, NULL) && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
{
// fprintf(stderr, "SetupDiGetDeviceInterfaceDetail - get length failed\n");
break;
}
// allocate space for device interface detail
dev_detail = (PSP_DEVICE_INTERFACE_DETAIL_DATA)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, detailLength);
if (!dev_detail)
{
// fprintf(stderr, "HeapAlloc failed\n");
break;
}
dev_detail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
// get device interface detail
if (!SetupDiGetDeviceInterfaceDetail(device_info, &device_interface, dev_detail, detailLength, NULL, NULL))
{
// fprintf(stderr, "SetupDiGetDeviceInterfaceDetail - get detail failed\n");
HeapFree(GetProcessHeap(), 0, dev_detail);
break;
}
StringCchCopy(tmp, path_len, dev_detail->DevicePath);
wcstombs(devpath[index], tmp, 256);
HeapFree(GetProcessHeap(), 0, dev_detail);
}
SetupDiDestroyDeviceInfoList(device_info);
// //禁用启用设备
// EnableDisableDevice();
return index;
}
HANDLE open_devices(char* device_base_path, char* device_name, DWORD accessFlags)
{
char device_path[MAX_PATH + 1] = "";
wchar_t device_path_w[MAX_PATH + 1];
HANDLE h;
// extend device path to include target device node (xdma_control, xdma_user etc)
verbose_msg("Device base path: %s\n", device_base_path);
strcpy_s(device_path, sizeof device_path, device_base_path);
strcat_s(device_path, sizeof device_path, device_name);
verbose_msg("Device node: %s\n", device_name);
// open device file
mbstowcs(device_path_w, device_path, sizeof(device_path));
h = CreateFile(device_path_w, accessFlags, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
qDebug() << QString::fromWCharArray(device_path_w) ;
// qDebug << "open_devices : " << QString::fromStdString(device_path_w) ;
if (h == INVALID_HANDLE_VALUE)
{
fprintf(stderr, "Error opening device, win32 error code: %ld\n", GetLastError());
}
return h;
}
static int read_device(HANDLE device, long address, DWORD size, BYTE* buffer)
{
DWORD rd_size = 0;
unsigned int transfers;
unsigned int i;
if (INVALID_SET_FILE_POINTER == SetFilePointer(device, address, NULL, FILE_BEGIN))
{
fprintf(stderr, "Error setting file pointer, win32 error code: %ld\n", GetLastError());
return -3;
}
// qDebug() << "Start ";
transfers = (unsigned int)(size / MAX_BYTES_PER_TRANSFER);
for (i = 0; i < transfers; i++)
{
if (!ReadFile(device, (void*)(buffer + i * MAX_BYTES_PER_TRANSFER), (DWORD)MAX_BYTES_PER_TRANSFER, &rd_size, NULL))
{
return -1;
}
if (rd_size != MAX_BYTES_PER_TRANSFER) //采集到的数据大小不到MAX_BYTES_PER_TRANSFER异常
{
return -2;
}
qDebug() << "Each 8M Unit: " << QString::number(i * MAX_BYTES_PER_TRANSFER, 16) ;
}
long addressLeave = address + transfers * MAX_BYTES_PER_TRANSFER;
if (INVALID_SET_FILE_POINTER == SetFilePointer(device, addressLeave, NULL, FILE_BEGIN))
{
fprintf(stderr, "Error setting file pointer, win32 error code: %ld\n", GetLastError());
return -3;
}
if (!ReadFile(device, (void*)(buffer + i * MAX_BYTES_PER_TRANSFER), (DWORD)(size - i * MAX_BYTES_PER_TRANSFER), &rd_size, NULL))
{
return -1;
}
if (rd_size != (size - i * MAX_BYTES_PER_TRANSFER)) //采集到的数据大小不到(size - i * MAX_BYTES_PER_TRANSFER),异常
{
return -2;
}
return size;
}
static int write_device(HANDLE device, long address, DWORD size, BYTE* buffer)
{
// fprintf(stderr, "........Enter Write device.........");
DWORD wr_size = 0;
unsigned int transfers;
unsigned int i;
transfers = (unsigned int)(size / MAX_BYTES_PER_TRANSFER);
// qDebug() << "write_device " << address;
if (INVALID_SET_FILE_POINTER == SetFilePointer(device, address, NULL, FILE_BEGIN))
{
fprintf(stderr, "Error setting file pointer, win32 error code: %ld\n", GetLastError());
return -3;
}
for (i = 0; i < transfers; i++)
{
if (!WriteFile(device, (void*)(buffer + i * MAX_BYTES_PER_TRANSFER), MAX_BYTES_PER_TRANSFER, &wr_size, NULL))
{
return -1;
}
if (wr_size != MAX_BYTES_PER_TRANSFER)
{
return -2;
}
}
long addressLeave = address + transfers * MAX_BYTES_PER_TRANSFER;
if (INVALID_SET_FILE_POINTER == SetFilePointer(device, addressLeave, NULL, FILE_BEGIN))
{
fprintf(stderr, "Error setting file pointer, win32 error code: %ld\n", GetLastError());
return -3;
}
if (!WriteFile(device, (void*)(buffer + i * MAX_BYTES_PER_TRANSFER), (DWORD)(size - i * MAX_BYTES_PER_TRANSFER), &wr_size, NULL))
{
return -1;
}
if (wr_size != (size - i * MAX_BYTES_PER_TRANSFER))
{
return -2;
}
return size;
}
bool Pcie_ReadControlRegData(unsigned int address, unsigned int size, unsigned char* buffer)
{
if (h_control == INVALID_HANDLE_VALUE)
{
return false;
}
int iCaptureSize = read_device(h_control, address, size, buffer);
if (iCaptureSize < 0)
{
return false;
}
return true;
}
int Pcie_WriteControlRegData(unsigned int address, unsigned char* buffer)
{
if (h_control == INVALID_HANDLE_VALUE)
{
return false;
}
int iCaptureSize = write_device(h_control, address, 4, buffer);
if (iCaptureSize < 0)
{
return false;
}
return true;
}
bool Pcie_ReadData(unsigned int address, unsigned int size, unsigned char* buffer)
{
if (h_c2h0 == INVALID_HANDLE_VALUE)
{
return false;
}
int iCaptureSize = read_device(h_c2h0, address, size, buffer);
if (iCaptureSize < 0)
{
return false;
}
return true;
}
bool Pcie_WriteData(unsigned int address, unsigned int size, unsigned char* buffer)
{
if (h_h2c0 == INVALID_HANDLE_VALUE)
{
return false;
}
int iInjectSize = write_device(h_h2c0, address, size, buffer);
if (iInjectSize < 0)
{
return false;
}
return true;
}
bool Pcie_WriteRegCmdData(unsigned int address, unsigned char* buffer, int length)
{
QMutexLocker locker(&g_regControlMutex);
if (h_user == INVALID_HANDLE_VALUE)
{
return false;
}
write_device(h_user, address, length, buffer);
return true;
}
bool Pcie_ReadRegCmdData(unsigned int address, unsigned char* buffer, int length)
{
QMutexLocker locker(&g_regControlMutex);
if (h_user == INVALID_HANDLE_VALUE)
{
return false;
}
read_device(h_user, address, length, buffer);
return true;
}
int Pcie_WriteReg(unsigned int address, unsigned char* buffer)
{
QMutexLocker locker(&g_regControlMutex);
if (h_user == INVALID_HANDLE_VALUE)
{
return -1;
}
int iStatus = 4;
iStatus = write_device(h_user, address, 4, buffer);
return iStatus;
}
DWORD Pcie_AcquireReg(unsigned int address, bool& isSuccess)
{
QMutexLocker locker(&g_regControlMutex);
if (h_user == INVALID_HANDLE_VALUE)
{
isSuccess = false;
return 0;
}
DWORD value = 0;
int status = read_device(h_user, address, 4, (BYTE*)&value);
if (status < 0)
{
isSuccess = false;
}
else
{
isSuccess = true;
}
return value;
}
DWORD Pcie_ReadReg(unsigned int address)
{
QMutexLocker locker(&g_regControlMutex);
if (h_user == INVALID_HANDLE_VALUE)
{
return 0;
}
DWORD value = 0;
read_device(h_user, address, 4, (BYTE*)&value);
return value;
}
void Pcie_CloseCard()
{
if (m_bIsCardOpen)
{
if (h_user != INVALID_HANDLE_VALUE)
{
user_start_en = 0x00000000;
write_device(h_user, 0x04, 4, (BYTE*)&user_start_en); //clear irq
CloseHandle(h_user);
h_user = INVALID_HANDLE_VALUE;
}
if (h_c2h0 != INVALID_HANDLE_VALUE)
{
CloseHandle(h_c2h0);
h_c2h0 = INVALID_HANDLE_VALUE;
}
if (h_h2c0 != INVALID_HANDLE_VALUE)
{
CloseHandle(h_h2c0);
h_h2c0 = INVALID_HANDLE_VALUE;
}
if (h_control != INVALID_HANDLE_VALUE)
{
CloseHandle(h_control);
h_control = INVALID_HANDLE_VALUE;
}
m_bIsCardOpen = false;
}
}
bool Pcie_OpenCard(char* devicepath)
{
//禁用启用设备
Pcie_CloseCard();
char user_name[] = "\\user";
char c2h0_name[] = "\\c2h_0";
char h2c0_name[] = "\\h2c_0";
char control_name[] = "\\control";
qDebug() << "xxx55 " << QDateTime::currentDateTime().toString("hh:mm:ss.zzz");
h_user = open_devices(devicepath, user_name, GENERIC_READ | GENERIC_WRITE);
if (h_user == INVALID_HANDLE_VALUE)
return false;
uint resetValue = 1;
qDebug() << "xxx11 " << QDateTime::currentDateTime().toString("hh:mm:ss.zzz");
write_device(h_user, ControlRegBaseAddr + 0x014, 4, (BYTE*)&resetValue); // 复位采集卡
QThread::msleep(50); //等待FPGA复位 清除上一次的数据
CloseHandle(h_user);
h_user = INVALID_HANDLE_VALUE;
//禁用启用设备
EnableDisableDevice();
qDebug() << "xxx44 " << QDateTime::currentDateTime().toString("hh:mm:ss.zzz");
h_user = open_devices(devicepath, user_name, GENERIC_READ | GENERIC_WRITE);
if (h_user == INVALID_HANDLE_VALUE)
return false;
h_h2c0 = open_devices(devicepath, h2c0_name, GENERIC_WRITE);
if (h_h2c0 == INVALID_HANDLE_VALUE)
return false;
h_c2h0 = open_devices(devicepath, c2h0_name, GENERIC_READ);
if (h_c2h0 == INVALID_HANDLE_VALUE)
return false;
h_control = open_devices(devicepath, control_name, GENERIC_READ);
if (h_control == INVALID_HANDLE_VALUE)
return false;
// open_event();
user_start_en = 0xffff0000;
write_device(h_user, 0x04, 4, (BYTE*)&user_start_en); //start irq
m_bIsCardOpen = true;
return true;
}
bool EnableDisableDevice()
{
HDEVINFO hDevInfo = SetupDiGetClassDevs(nullptr, nullptr, nullptr, DIGCF_ALLCLASSES | DIGCF_PRESENT);
if (hDevInfo == INVALID_HANDLE_VALUE)
return false;
SP_DEVINFO_DATA devInfoData;
devInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
bool success = false;
for (DWORD i = 0; SetupDiEnumDeviceInfo(hDevInfo, i, &devInfoData); ++i)
{
WCHAR deviceId[MAX_DEVICE_ID_LEN];
if (CM_Get_Device_IDW(devInfoData.DevInst, deviceId, MAX_DEVICE_ID_LEN, 0) == CR_SUCCESS)
{
// qDebug() << "deviceId List " << i << " " << QString::fromWCharArray(deviceId) << deviceId;
if (QString::fromWCharArray(deviceId).contains("VEN_10EE")) //xilinx设备
{
bool isSuccess = false;
int code = CM_Disable_DevNode(devInfoData.DevInst, CM_DISABLE_POLITE);
if (code == CR_SUCCESS)
{
isSuccess = true;
}
qDebug() << "isSuccess01 : " << isSuccess << GetLastError() ;
Sleep(20);
isSuccess = false;
if (CM_Enable_DevNode(devInfoData.DevInst, 0) == CR_SUCCESS)
{
isSuccess = true;
}
qDebug() << "isSuccess02 : " << isSuccess << GetLastError() ;
Sleep(20);
}
}
}
SetupDiDestroyDeviceInfoList(hDevInfo);
return success;
}
bool Pcie_IsCardOpen()
{
return m_bIsCardOpen;
}