📄 pcidp_if.cpp
字号:
//*****************************************************************************
// Copyright (C) 2000, Cypress Semiconductor.
//
// ALL RIGHTS RESERVED. USE, DISCLOSURE, OR REPRODUCTION WITHOUT WRITTEN
// PERMISSION OF CYPRESS SEMICONDUCTOR IS PROHIBITED.
//
//
// This is PCIDP_IF.cpp. It provides direct access to the PCIDP
// kernel driver under Windows NT/2000.
//
// NOTE: for optimal readability set your TABs option to 2 spaces.
//*****************************************************************************
#include "windows.h"
#include "process.h"
#include "WinIoCtl.h"
#include "PCIDP_IF_KRNL.h"
#include "PCIDP.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 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;
// Initialize variables.
Device[10] = (char)BoardNumber + 0x30;
// 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
);
// 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;
// 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[10] = (char)BoardNumber + 0x30;
// 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
);
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;
}
}
else
RTNStatus = ERROR_INVALID_HANDLE;
return RTNStatus;
}
// ----------------------------------------------------------------------------
// MapBaseRegister -
// ----------------------------------------------------------------------------
unsigned long Krnl_MapBaseRegister(
in unsigned long PCIDPHandle,
in unsigned long RegisterNumber,
in out unsigned long* Length,
out unsigned long** Address,
out unsigned long* IOAddress,
out unsigned long* IOSpace
){
// Declare variables.
unsigned long RTNStatus;
PCIDP00_MAP_BASE_REGS_SEND Input;
PCIDP00_MAP_BASE_REGS_RECV Output;
unsigned long BoardNumber;
// Initialize variables.
Input.RegNumber = RegisterNumber;
Input.Length = *Length;
// Validate the handle.
if((PCIDPHandle & 0xFFFFF000) == 0xF0CEB000){
// Request the kernel service Map Base Regs.
BoardNumber = PCIDPHandle & 0x7;
RTNStatus = RequestService(
BoardNumber,
IOCTL_PCIDP00_MAP_BASE_REGS,
&Input,
&Output,
sizeof(Input),
sizeof(Output)
);
if(RTNStatus == ERROR_SUCCESS){
*Length = Output.Length;
*IOSpace = Output.IOSpace;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -