⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pcidp_if.cpp

📁 一个amccs5933芯片的驱动程序开发源程序和部分文档
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//*****************************************************************************
// 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 + -