📄 pcidp_if.cpp
字号:
//*****************************************************************************
// THIS CODE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
// OR IMPLIED. THIS CODE IS LABELED "OPEN SOFTWARE" AND MAY BE FREELY USED,
// REPRODUCED, MODIFIED, AND/OR REDISTRIBUTED WITH THE STIPULATION THAT THIS
// NOTICE REMAIN INTACT. REDISTRIBUTION OF ANY KIND IMPLIES THAT ALL
// MODIFICATIONS FALL UNDER THIS "OPEN SOFTWARE" LABEL.
//
// Copyright (C) 2002, Foxen Solutions
// Copyright (C) 2002, FXN
//
// All Rights Reserved.
//*****************************************************************************
#include "windows.h"
#include "process.h"
#include "WinIoCtl.h"
#include "PCIDP_IF_KRNL.h"
#include "PCIDP.h"
#include "initguid.h"
#include "PCIDPGUID.h"
#include "SETUPAPI.h"
// Define structures used with the services.
typedef struct {
HANDLE HDriver;
PCIDP00_REGISTER_INTERRUPT_SEND Input;
OVERLAPPED AsyncOvl;
HANDLE EndEvent;
HANDLE SyncEvent;
HANDLE IntEvent;
} THREAD_PARAMS, *pTHREAD_PARAMS;
// Declare global variables local to the application.
unsigned long Handles[] = {0,0,0,0,0,0,0,0};
//char Device[] = "\\\\.\\PCIDP00"; //Win32 device name for PCIDP driver
HANDLE DMAHDriver;
// Define protected routines that provide services for the public routines.
void InterruptThread(LPVOID Params){
pTHREAD_PARAMS ThreadParams = (pTHREAD_PARAMS)Params;
BOOL Status;
unsigned long WaitStatus;
unsigned long BytesReturned;
const unsigned long SyncEvent = WAIT_OBJECT_0 + 1;
// Wait for the Sync event initiated by this thread's creation process.
WaitStatus = WaitForMultipleObjects(
2,
&ThreadParams->EndEvent,
FALSE,
INFINITE
);
// Loop as long as the SyncEvent is the one signaled.
while(WaitStatus == SyncEvent){
// The interrupt has triggered. Reset its corresponding event then
// request another I/O association with the interrupt.
ResetEvent(ThreadParams->SyncEvent);
DeviceIoControl(
ThreadParams->HDriver,
(DWORD) IOCTL_PCIDP00_REGISTER_INTERRUPT,
&ThreadParams->Input,
sizeof(PCIDP00_REGISTER_INTERRUPT_SEND),
NULL,
0,
&BytesReturned,
&ThreadParams->AsyncOvl
);
// Set requesting applicaiton's interrupt event. It is up to the
// calling application to reset this event.
SetEvent(ThreadParams->IntEvent);
// Wait for the interrupt to trigger again and repeat the process.
if(GetLastError() == ERROR_IO_PENDING){
WaitStatus = WaitForMultipleObjects(
2,
&ThreadParams->EndEvent,
FALSE,
INFINITE
);
}
else
;
//we're screwed!! -- only error is: out of non-paged memory.
//keep trying
}
// To get here means the EndEvent event flag was signaled. Time to close
// up shop.
Status = DeviceIoControl(
ThreadParams->HDriver,
(DWORD) IOCTL_PCIDP00_UNREGISTER_INTERRUPT,
&ThreadParams->Input,
sizeof(PCIDP00_REGISTER_INTERRUPT_SEND),
NULL,
0,
&BytesReturned,
NULL
);
if(Status == FALSE)
WaitStatus = GetLastError();
CloseHandle(ThreadParams->HDriver);
CloseHandle(ThreadParams->IntEvent);
CloseHandle(ThreadParams->EndEvent);
CloseHandle(ThreadParams->SyncEvent);
delete ThreadParams;
_endthread();
}
unsigned long EnumerateBoards(
unsigned long BoardNumber,
char* Device,
unsigned long Length
){
unsigned long RtnLength = 0;
HDEVINFO DevInfoSet;
SP_DEVINFO_DATA DevInfoData;
SP_DEVICE_INTERFACE_DATA DevInterfaceData;
char* DevInterfaceDetailExt;
PSP_DEVICE_INTERFACE_DETAIL_DATA DevInterfaceDetail;
DWORD RequiredSize;
BOOLEAN Status;
// Get the device information set for the PCIDP.
DevInfoSet = SetupDiGetClassDevs(
IN (struct _GUID*)&GUID_PCIDP_INTERFACE,
IN NULL, //"PCIDP Development Board"
IN NULL,
IN DIGCF_DEVICEINTERFACE | DIGCF_PRESENT
);
// Get the device informatiion data for the device corresponding
// to the board number.
DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
Status = SetupDiEnumDeviceInfo(
IN DevInfoSet,
IN BoardNumber,
OUT &DevInfoData
);
// Get the first (and only) interface data for the device.
if(Status == FALSE) goto Exit;
DevInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
Status = SetupDiEnumDeviceInterfaces(
IN DevInfoSet,
IN &DevInfoData,
IN (struct _GUID*)&GUID_PCIDP_INTERFACE,
IN 0,
OUT &DevInterfaceData
);
// Get the size of the detailed information buffer.
if(Status == FALSE) goto Exit;
Status = SetupDiGetDeviceInterfaceDetail(
IN DevInfoSet,
IN &DevInterfaceData,
OUT NULL,
IN 0,
OUT &RequiredSize,
OUT NULL
);
// Now retreive the detailed information.
if(GetLastError() == ERROR_INSUFFICIENT_BUFFER){
DevInterfaceDetailExt = new char[RequiredSize];
DevInterfaceDetail = (PSP_DEVICE_INTERFACE_DETAIL_DATA)DevInterfaceDetailExt;
DevInterfaceDetail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
Status = SetupDiGetDeviceInterfaceDetail(
IN DevInfoSet,
IN &DevInterfaceData,
OUT DevInterfaceDetail,
IN RequiredSize,
OUT 0,
OUT NULL
);
// Now return the device path name.
if(Status == TRUE){
strncpy(Device, DevInterfaceDetail->DevicePath, Length-1);
Device[Length-1] = 0;
RtnLength = strlen(Device)+1;
}
delete DevInterfaceDetailExt;
}
Exit:
SetupDiDestroyDeviceInfoList(DevInfoSet);
return RtnLength;
}
unsigned long RequestService(
unsigned long BoardNumber,
unsigned long ControlFunction,
void* InputBuffer,
void* OutputBuffer,
unsigned long InputSize,
unsigned long OutputSize
){
// Declare variables.
unsigned long RTNStatus;
BOOL Status;
HANDLE HDriver;
DWORD BytesReturned;
char* Device;
unsigned long DeviceLength = 200;
Device = new char[DeviceLength];
RTNStatus = EnumerateBoards(BoardNumber, Device, DeviceLength);
if(RTNStatus == DeviceLength){
delete Device;
DeviceLength *= 2;
Device = new char[DeviceLength];
RTNStatus = EnumerateBoards(BoardNumber, Device, DeviceLength);
}
// Create a "file" object with which to communicate I/O requests.
HDriver = CreateFile(
Device,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
delete Device;
// Now "call" the driver via the system DeviceIoControl service.
if(HDriver != INVALID_HANDLE_VALUE){
Status = DeviceIoControl(
HDriver,
ControlFunction,
InputBuffer,
InputSize,
OutputBuffer,
OutputSize,
&BytesReturned,
0
);
if(Status == TRUE)
RTNStatus = ERROR_SUCCESS;
else
RTNStatus = GetLastError();
CloseHandle(HDriver);
}
else
RTNStatus = GetLastError();
return RTNStatus;
}
unsigned long CancelMapDMAMemory(
in unsigned long PCIDPHandle,
in unsigned long* Address
){
// Declare variables.
unsigned long RTNStatus;
PCIDP00_UNMAP_DMA_SEND Input;
unsigned long BoardNumber;
unsigned long BytesReturned;
OVERLAPPED AsyncOvl;
char* Device;
unsigned long DeviceLength = 200;
// Initialize variables.
AsyncOvl.hEvent = 0;
Input.LinearAddress = (unsigned long)Address;
// Validate the handle.
if((PCIDPHandle & 0xFFFFF000) == 0xF0CEB000){
// Open the connection between the application and the driver.
// This connection supports asynchonous I/O so we can return
// immedidately.
// Set up the device name based on board number.
BoardNumber = PCIDPHandle & 0x7;
Device = new char[DeviceLength];
RTNStatus = EnumerateBoards(BoardNumber, Device, DeviceLength);
if(RTNStatus == DeviceLength){
delete Device;
DeviceLength *= 2;
Device = new char[DeviceLength];
RTNStatus = EnumerateBoards(BoardNumber, Device, DeviceLength);
}
// Create a "file" object with which to communicate I/O requests.
DMAHDriver = CreateFile(
Device,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
NULL
);
delete Device;
if(DMAHDriver == INVALID_HANDLE_VALUE){
RTNStatus = GetLastError();
goto ExitA;
}
// Now "call" the driver to register the cancel DMA using the system
// DeviceIoControl service.
DeviceIoControl(
DMAHDriver,
(DWORD) IOCTL_PCIDP00_CANCEL_MAP_DMA,
&Input,
sizeof(PCIDP00_UNMAP_DMA_SEND),
NULL,
0,
&BytesReturned,
&AsyncOvl
);
RTNStatus = GetLastError();
if(RTNStatus != ERROR_IO_PENDING) CloseHandle(DMAHDriver);
}
else
RTNStatus = ERROR_INVALID_HANDLE;
ExitA:
return RTNStatus;
}
// ----------------------------------------------------------------------------
// OpenPCIDP -
// ----------------------------------------------------------------------------
unsigned long Krnl_OpenPCIDP(
in unsigned long BoardNumber,
out unsigned long* PCIDPHandle
){
// Define variables.
unsigned long RTNStatus;
// Check for a valid board number.
if(BoardNumber < 8){
// The driver for this board/application pair has not been opened.
if(Handles[BoardNumber] == 0){
// Request the kernel service Hello, just to see if the device
// exists.
RTNStatus = RequestService(
BoardNumber,
IOCTL_PCIDP00_HELLO, //control function
NULL, //input buffer
NULL, //output buffer
0, //input buffer size
0 //output buffer size
);
if(RTNStatus == ERROR_SUCCESS){
Handles[BoardNumber] = BoardNumber | 0xF0CEB000;
*PCIDPHandle = Handles[BoardNumber];
}
}
else{
*PCIDPHandle = Handles[BoardNumber];
RTNStatus = ERROR_SUCCESS;
}
}
else
RTNStatus = ERROR_BAD_DEVICE;
return RTNStatus;
}
// ----------------------------------------------------------------------------
// GetDriverVersion -
// ----------------------------------------------------------------------------
unsigned long Krnl_GetDriverVersion(
in unsigned long PCIDPHandle,
out unsigned long* Version
){
// Declare variables.
unsigned long RTNStatus;
PCIDP00_GET_VERSION_SEND Input;
PCIDP00_GET_VERSION_RECV Output;
unsigned long BoardNumber;
// Validate the handle.
if((PCIDPHandle & 0xFFFFF000) == 0xF0CEB000){
// Request the kernel service Get Driver Version.
BoardNumber = PCIDPHandle & 0x7;
RTNStatus = RequestService(
BoardNumber,
IOCTL_PCIDP00_GET_VERSION,
&Input,
&Output,
sizeof(Input),
sizeof(Output)
);
if(RTNStatus == ERROR_SUCCESS){
*Version = Output.Version;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -