📄 pcietest.cpp
字号:
/*++
Copyright (c) Microsoft Corporation
Module Name:
plx.cpp
Abstract:
This module implements the PCIE class which tests the DMA of PCIE devices.
Example usage:
plx.exe /wr /wb=100 # write-then-read once with a buffer of 100 bytes
plx.exe /thread # repeat write-then-read for default 5000 millisecs.
plx.exe /thread /time=1000 # repeat write-then-read for 1000 millisecs.
NOTE: The /quite option will suppress most non-error messages.
NOTE: The options and parameters are case sensitive.
Environment:
User Mode Win2k or Later
--*/
#define INITGUID
#include <windows.h>
#include <Winsvc.h>
#include <winioctl.h>
#include "pcietest.hpp"
#include "freq.h"
//
// Define the spin count to be used for critical sections. The value
// specified below is arbitrary. Change it based on your requirements.
//
#define SPIN_COUNT_FOR_CS 0x4000
int g_TimeUp =0;
DWORD WINAPI
ReadThreadProc(
LPVOID lpParameter
)
{
ULONG bytes;
PTHREAD_CONTEXT Context = (PTHREAD_CONTEXT)lpParameter;
while(!g_TimeUp) {
if(ReadFile(Context->hDevice,
Context->Buffer,
Context->BufferSize,
&bytes,
NULL)) {
if (!Context->quite) {
printf("Read sucessful.\n");
}
} else {
printf("Read failed.\n");
ExitProcess(1);
}
}
ExitThread(0);
}
DWORD WINAPI
WriteThreadProc(
LPVOID lpParameter
)
{
ULONG bytes;
PTHREAD_CONTEXT Context = (PTHREAD_CONTEXT)lpParameter;
while(!g_TimeUp) {
if(WriteFile(Context->hDevice,
Context->Buffer,
Context->BufferSize,
&bytes,
NULL)) {
if (!Context->quite) {
printf("Write sucessful.\n");
}
} else {
printf("Write failed.\n");
ExitProcess(1);
}
}
ExitThread(0);
}
int __cdecl
main(
__in int argc,
__in_ecount(argc) char* argv[]
)
{
PCIE Pcie;
BOOL status = TRUE;
ULONG test = MENU_TEST;
if (!Pcie.Initialize()) {
printf("Failied to Initialize Test class.\n");
printf("exit(%d)\n", Pcie.Status);
exit(Pcie.Status);
}
if(argc > 1) {
for(int i=1; (i < argc) && status; i++) {
char delims[] = "-/=";
char delims2[] = "=";
char *command;
char *data;
data = NULL;
command = strtok(argv[i], delims );
if(command == NULL) {
status = FALSE;
break;
}
if(strcmp(command, "rb") == 0) {
data = strtok(NULL, delims2);
if (!data && i < argc-1) {
data = argv[++i];
}
ULONG size = atol(data);
if (size > 0) {
Pcie.SetReadBufferSize(size);
} else {
status = FALSE;
}
} else if(strcmp(command, "wb") == 0) {
ULONG size = 0;
data = strtok(NULL, delims2);
if (!data && i < argc-1) {
data = argv[++i];
}
if (data) {
size = atol(data);
}
if (size > 0) {
Pcie.SetWriteBufferSize(size);
} else {
status = FALSE;
}
} else if (strcmp(command, "bs") == 0) {
data = strtok(NULL, delims2);
if (!data && i < argc-1) {
data = argv[++i];
}
ULONG size = atol(data);
if(size > 0) {
Pcie.SetWriteBufferSize(size);
} else {
status = FALSE;
}
} else if(strcmp(command, "wt") == 0) {
test = WRITE_TEST;
} else if(strcmp(command, "rt") == 0) {
test = READ_TEST;
} else if(strcmp(command, "quite") == 0) {
Pcie.Quite = TRUE;
} else if(strcmp(command, "thread") == 0) {
test = THREAD_TEST;
} else if (strcmp(command, "time") == 0) {
data = strtok(NULL, delims);
if(!data && i < argc-1) {
data = argv[++i];
}
ULONG size = atol(data);
Pcie.SetThreadLifeTime(size);
} else {
status = FALSE;
}
if (!Pcie.Quite) {
if (data) {
printf("Arg %d: Command: %s Parameter: %s\n", i, command, data);
} else {
printf("Arg %d: Command: %s\n", i, command);
}
}
}
}
if (status) {
switch (test) {
case READ_TEST:
Pcie.ReadTest();
break;
case WRITE_TEST:
Pcie.WriteTest();
break;
case READ_WRITE_TEST:
Pcie.ReadWriteTest();
break;
case THREAD_TEST:
Pcie.ThreadedReadWriteTest();
break;
case MENU_TEST:
default:
Pcie.Menu();
}
} else {
printf("Invalid command line parameter.\n");
Pcie.Status = 1;
}
printf("exit(%d)\n", Pcie.Status);
exit( Pcie.Status );
}
PCIE::PCIE()
{
ReadBuffer = WriteBuffer = NULL;
hDevInfo = pDeviceInterfaceDetail = NULL;
hDevice = INVALID_HANDLE_VALUE;
console = TRUE;
Contexts = NULL;
Threads = NULL;
ProcessorCount = 0;
CSInitialized = FALSE;
ThreadTimer = 5000; // 5000 milliseconds (5 seconds)
Quite = FALSE;
Status = 0;
}
PCIE::~PCIE()
{
if (CSInitialized) {
DeleteCriticalSection(&CriticalSection);
}
if (hDevInfo) {
SetupDiDestroyDeviceInfoList(hDevInfo);
}
if (pDeviceInterfaceDetail) {
free(pDeviceInterfaceDetail);
}
if (Contexts) {
for(int i = 0; i < ProcessorCount; i++) {
if (Contexts[i].Buffer) {
delete Contexts[i].Buffer;
}
}
delete Contexts;
Contexts = NULL;
}
if (hDevice != INVALID_HANDLE_VALUE) {
CloseHandle(hDevice);
hDevice = INVALID_HANDLE_VALUE;
}
}
BOOL
PCIE::Initialize()
{
BOOL retValue = TRUE;
retValue = SetBufferSizes(DEFAULT_READ_BUFFER_SIZE);
if (!retValue) {
return retValue;
}
retValue = GetDevicePath();
if (!retValue) {
return retValue;
}
if (!CSInitialized) {
retValue = InitializeCriticalSectionAndSpinCount(&CriticalSection, SPIN_COUNT_FOR_CS);
if (!retValue) {
printf("InitializeCritialSection failed.\n");
Status = GetLastError();
return retValue;
}
CSInitialized = TRUE;
}
return retValue;
}
void
PCIE::Menu()
{
int menu = -1;
while(menu != 0 && pDeviceInterfaceDetail) {
printf("\n"
" 1- Read from device\n"
" 2- Write from device\n"
" 3- Read/Write from device\n"
" 4- Read/Write Thread Test\n"
" 5- Select new device\n"
" 6- Change Buffer Size\n"
" 7- Compare Read/Write Buffers\n"
" 8- Display Read/Write Buffers\n"
" 9- Change Thread Lifetime\n"
"10- Command Line Options\n"
" 0- Quit\n");
if (scanf_s("%d", &menu) == 0) {
break;
}
switch(menu) {
case READ_TEST: // 1
ReadTest();
break;
case WRITE_TEST: // 2
WriteTest();
break;
case READ_WRITE_TEST: // 3
ReadWriteTest();
break;
case THREAD_TEST: // 4
ThreadedReadWriteTest();
break;
case DEVICE_PATH: // 5
GetDevicePath();
break;
case SET_SIZE: // 6
ULONG size;
printf("\nEnter new buffer size: ");
if (scanf_s("%d", &size) != 0) {
SetBufferSizes(size);
}
break;
case COMPARE_BUFFERS: // 7
CompareReadWriteBuffers();
break;
case DISPLAY_BUFFERS: // 8
DisplayReadWriteBuffers();
break;
case THREAD_TIME: // 9
printf("\nEnter new Thread Lifetime (ms): ");
if (scanf_s("%d", &ThreadTimer) == 0) {
break;
}
break;
case COMMAND_LINE: // 10
printf("Command Line Options\n"
" Set Read Buffer Size: '/rb=xx'\n"
" Set Write Buffer Size: '/wb=xx'\n"
" Set Both Buffer Sizes: '/bs=xx'\n"
" Perform Write Test: '/wt'\n"
" Perform Read Test: '/rt'\n"
" Perform Read/Write Test: '/wr'\n"
" Perform Read/Write Thread Test: '/thread'\n");
break;
default:
break;
}
}
}
BOOL
PCIE::ThreadedReadWriteTest()
{
BOOL status = TRUE;
DWORD_PTR pAffinity, sAffinity;
int i;
HANDLE hThread;
HANDLE hProcess = GetCurrentProcess();
GetProcessAffinityMask(hProcess, &pAffinity, &sAffinity);
ProcessorCount = 0;
while(pAffinity) {
ProcessorCount++;
pAffinity = pAffinity >> 1;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -