📄 pcidp.c
字号:
//*****************************************************************************
// THIS CODE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
// OR IMPLIED. THIS CODE IS COPYRIGHTED AND MAY NOT BE MODIFIED OR DISTRIBUTED
// WITHOUT THE WRITTEN CONSENT OF THE PRODUCER.
//
// Copyright (C) 2002, Foxen Solutions
// Copyright (C) 2002, FXN
//
// All Rights Reserved.
//*****************************************************************************
//
// ----------------------------------------------------------------------------
// This is PCIDP.c. It is the Windows 2000 kernal mode driver for the PCI-DP
// CY7C09449PV-AC board.
//
// NOTE: Best viewed with Tabs set to 2.
// ----------------------------------------------------------------------------
// Issues to resolve are marked //todo
// Include the appropriate header files.
#include "PCIDPInc.h"
#include "PCIDP.h"
#include "initguid.h"
#include "PCIDPGUID.h"
// ----------------------------------------------------------------------------
// DriverEntry is the entry point for the PCIDP kernel mode driver. Windows
// 2000 calls this routine to initialize this driver.
// ----------------------------------------------------------------------------
NTSTATUS DriverEntry(
IN OUT PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
){
// Debug entry point
//DbgPrint("[PCIDP]->Entering DriverEntry...\n"); //debug
//DbgBreakPoint(); //debug
// Initialize the driver object with this driver's entry points.
DriverObject->MajorFunction[IRP_MJ_CREATE] = PCIDPCreateClose;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = PCIDPCreateClose;
DriverObject->DriverExtension->AddDevice = PCIDPAddDevice;
DriverObject->MajorFunction[IRP_MJ_PNP] = PCIDPDispatchPnp;
DriverObject->MajorFunction[IRP_MJ_POWER] = PCIDPDispatchPower;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = PCIDPDeviceControl;
DriverObject->MajorFunction[IRP_MJ_CLEANUP] = PCIDPCleanup;
DriverObject->DriverUnload = (PDRIVER_UNLOAD)PCIDPUnload;
//DriverObject->DriverStartIo = (PDRIVER_STARTIO)PCIDPStartIo; //to have OS manage queued IRPs
// Initialize any other driver global data.
// Save a copy of the registry path pointed to by RegistryPath.
// Register for driver reinitialization.
// IoRegisterDriverReinitialization();
return STATUS_SUCCESS;
}
// ----------------------------------------------------------------------------
// PCIDPAddDevice. Called by the Windows 2000 Plug and Play manager to add a
// device that is controlled by this driver.
// ----------------------------------------------------------------------------
NTSTATUS PCIDPAddDevice(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT PhysicalDeviceObject
){
NTSTATUS NTStatus;
PDEVICE_OBJECT DeviceObject;
PPCIDP_EXTENSION ObjExt;
PHYSICAL_ADDRESS MaxAddress;
PHYSICAL_ADDRESS PhysicalAddress;
// Debug entry point
//DbgPrint("[PCIDP]->Entering AddDevice...\n"); //debug
//DbgBreakPoint(); //debug
// Create the device space that will be associated with this driver.
//todo: how to set up security attributes so the app. can call this driver
// (because of the FILE_DEVICE_SECURE_OPEN parameter).
NTStatus = IoCreateDevice(
IN DriverObject, // The driver object
IN sizeof(PCIDP_EXTENSION), // Size (bytes) of the device ext.
IN NULL, // The device name; let the OS name it
IN FILE_DEVICE_PCIDP00, // The device type
IN FILE_DEVICE_SECURE_OPEN, // Device characteristics
IN FALSE, // Exclusive Device flag
OUT &DeviceObject // New created device object
);
if(NTStatus != STATUS_SUCCESS)
goto Exit;
// Initialize the driver's extended object.
ObjExt = (PPCIDP_EXTENSION)DeviceObject->DeviceExtension;
RtlZeroMemory(ObjExt, sizeof(PCIDP_EXTENSION));
//ObjExt->BusNumber = BusNumber; - not needed
//ObjExt->SlotNumber = SlotNumber; - not needed
//ObjExt->BoardNumber = BoardNumber; - not needed
//ObjExt->BaseAddresses[0] = CardInfo.u.type0.BaseAddresses[0]; - not needed
//ObjExt->BaseAddresses[1] = CardInfo.u.type0.BaseAddresses[1]; - not needed
//ObjExt->BaseAddresses[2] = CardInfo.u.type0.BaseAddresses[2]; - not needed
//ObjExt->BaseAddresses[3] = CardInfo.u.type0.BaseAddresses[3]; - not needed
//ObjExt->BaseAddresses[4] = CardInfo.u.type0.BaseAddresses[4]; - not needed
//ObjExt->BaseAddresses[5] = CardInfo.u.type0.BaseAddresses[5]; - not needed
//ObjExt->MemoryAccess - enum resources (Start)
//ObjExt->IOAccess - enum resources (Start)
//ObjExt->MemoryAccessLength - enum resources (Start)
//ObjExt->IOAccessLength - enum resources (Start)
//ObjExt->MemoryBase - initialized by MmMapIoSpace call (Start)
//ObjExt->IOBase - not needed
//ObjExt->InterruptObject - initialized by IoConnectInterrupt call (Start)
//ObjExt->InterruptData - used in DpcISR and ISR
ObjExt->LLData.IsEmpty = TRUE;
ObjExt->LLData.CurrentLink = NULL;
ObjExt->LLData.InsertedCount = 0;
ObjExt->LLData.FreeMax = 0;
//ObjExt->LListSpin - initialized by KeInitializeSpinLock call (AddDevice)
//ObjExt->VirtualDMAAddress - initialized by MmAllocateContiguousMemory (AddDevice)
//ObjExt->PhysicalDMAAddress - initialized by MmGetPhysicalAddress (AddDevice)
//ObjExt->MDL - initialized by IoAllocateMdl (AddDevice)
//ObjExt->SymbolicLinkName - initialized by IoRegisterDeviceInterface (AddDevice)
//ObjExt->PhysicalDeviceObject - not needed
//ObjExt->NextLowerDeviceObject - initialized by IoAttachDeviceToDeviceStack (AddDevice)
//ObjExt->WaitEvent - initialized by KeInitializeEvent (AddDevice)
// Now create a symbolic link an application can use to gain access to the
// driver's services for this device.
NTStatus = IoRegisterDeviceInterface(
IN PhysicalDeviceObject, //The PDO
IN &GUID_PCIDP_INTERFACE, //GUID for the interface class
IN NULL, //Reference string (not used)
OUT &ObjExt->SymbolicLinkName //returned symbolic link name
);
if(NTStatus != STATUS_SUCCESS)
if(NTStatus != STATUS_OBJECT_NAME_EXISTS)
goto ExitA;
// Attach the device object to its device stack.
ObjExt->NextLowerDeviceObject = IoAttachDeviceToDeviceStack(
DeviceObject,
PhysicalDeviceObject
);
if(ObjExt->NextLowerDeviceObject == NULL){
NTStatus = STATUS_UNSUCCESSFUL; //todo: more meaningful error code or log event file
goto ExitA;
}
// Set up an synchro event for the start device IRP.
KeInitializeEvent(&ObjExt->WaitEvent, SynchronizationEvent, FALSE);
// Allocate a contiguous span of memory for DMA usage.
MaxAddress.LowPart = 0xFFFFFFFF;
MaxAddress.HighPart = 0;
ObjExt->VirtualDMAAddress = MmAllocateContiguousMemory(
IN (ULONG)DMASize, //16K
IN MaxAddress //Full 32 bit address range
);
//DbgPrint("[PCIDP]->AddDevice, VirtDMAAddr=0x%x...\n", ObjExt->VirtualDMAAddress); //debug
if(ObjExt->VirtualDMAAddress != NULL){
PhysicalAddress = MmGetPhysicalAddress(
ObjExt->VirtualDMAAddress
);
ObjExt->PhysicalDMAAddress = PhysicalAddress.LowPart;
//DbgPrint("[PCIDP]->AddDevice, PhyDMAAddr=0x%x...\n", ObjExt->PhysicalDMAAddress); //debug
ObjExt->MDL = IoAllocateMdl(
ObjExt->VirtualDMAAddress,
DMASize,
FALSE,
FALSE,
NULL
);
if(ObjExt->MDL){
//DbgPrint("[PCIDP]->AddDevice, MDLFlags=0x%x...\n", ObjExt->MDL->MdlFlags); //debug
//MmBuildMdlForNonPagedPool(ObjExt->MDL);
//DbgPrint("[PCIDP]->AddDevice, MDLFlags=0x%x...\n", ObjExt->MDL->MdlFlags); //debug
MmProbeAndLockPages(
ObjExt->MDL,
KernelMode,
IoModifyAccess
);
//DbgPrint("[PCIDP]->AddDevice, MDLFlags=0x%x...\n", ObjExt->MDL->MdlFlags); //debug
}
}
// Could not allocate memory for DMA but that is not
// a show-stopper.
else
ObjExt->PhysicalDMAAddress = 0;
// To get here means we were successful.
DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
goto Exit;
ExitA:
IoDeleteDevice (DeviceObject);
Exit:
// Debug exit point
//DbgPrint("[PCIDP]->Leaving AddDevice, status=0x%x...\n", NTStatus); //debug
//DbgBreakPoint(); //debug
return NTStatus;
}
// ----------------------------------------------------------------------------
// PCIDPDispatchPower. Power management dispatch routine called by the Windows
// 2000 power manager.
// ----------------------------------------------------------------------------
NTSTATUS PCIDPDispatchPower(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
){
PPCIDP_EXTENSION ObjExt;
NTSTATUS NTStatus;
// Debug entry point
//DbgPrint("[PCIDP]->Entering DispatchPower...\n"); //debug
//DbgBreakPoint(); //debug
ObjExt = (PPCIDP_EXTENSION)DeviceObject->DeviceExtension;
PoStartNextPowerIrp(Irp);
IoSkipCurrentIrpStackLocation(Irp);
NTStatus = PoCallDriver(ObjExt->NextLowerDeviceObject, Irp);
// Debug exit point
//DbgPrint("[PCIDP]->Leaving DispatchPower, status=0x%x...\n", NTStatus); //debug
//DbgBreakPoint(); //debug
return STATUS_SUCCESS;
}
// ----------------------------------------------------------------------------
// PCIDPDispatchPnp. Plug and Play dispatch routine called by the Windows 2000
// PnP manager.
// ----------------------------------------------------------------------------
NTSTATUS PCIDPDispatchPnp(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
){
PIO_STACK_LOCATION IrpStack;
NTSTATUS NTStatus;
PPCIDP_EXTENSION ObjExt;
ObjExt = (PPCIDP_EXTENSION)DeviceObject->DeviceExtension;
// Get a pointer to the current location in the Irp. This is where
// the function codes and parameters are located.
IrpStack = IoGetCurrentIrpStackLocation(IN Irp);
// Debug entry point
//DbgPrint("[PCIDP]->Entering DispatchPnp, function=0x%x...\n",IrpStack->MinorFunction); //debug
//DbgBreakPoint(); //debug
// Determine the PnP I/O request packet.
switch (IrpStack->MinorFunction){
case IRP_MN_START_DEVICE:
NTStatus = StartDevice(DeviceObject, Irp);
Irp->IoStatus.Status = NTStatus;
//PoSetPowerState(DeviceObject, DevicePowerState, PowerDeviceD0);
IoCompleteRequest(Irp, IO_NO_INCREMENT); //back up the stack so complete it.
break;
case IRP_MN_QUERY_STOP_DEVICE:
//NTStatus = STATUS_UNSUCCESSFUL;
//Irp->IoStatus.Status = NTStatus;
//IoCompleteRequest(Irp, IO_NO_INCREMENT);
NTStatus = STATUS_SUCCESS;
Irp->IoStatus.Status = NTStatus;
IoSkipCurrentIrpStackLocation(Irp); //send it on down the stack
IoCallDriver(ObjExt->NextLowerDeviceObject, Irp);
break;
case IRP_MN_STOP_DEVICE:
NTStatus = StopDevice(DeviceObject);
IoSkipCurrentIrpStackLocation(Irp); //send it on down the stack
IoCallDriver(ObjExt->NextLowerDeviceObject, Irp);
break;
case IRP_MN_CANCEL_STOP_DEVICE:
NTStatus = CancelStopDevice(DeviceObject, Irp);
Irp->IoStatus.Status = NTStatus;
IoCompleteRequest(Irp, IO_NO_INCREMENT); //back up the stack so complete it.
break;
case IRP_MN_QUERY_REMOVE_DEVICE:
NTStatus = STATUS_UNSUCCESSFUL;
Irp->IoStatus.Status = NTStatus;
IoSkipCurrentIrpStackLocation(Irp); //send it on down the stack
IoCallDriver(ObjExt->NextLowerDeviceObject, Irp);
break;
case IRP_MN_REMOVE_DEVICE:
NTStatus = RemoveDevice(DeviceObject);
Irp->IoStatus.Status = NTStatus;
IoSkipCurrentIrpStackLocation(Irp); //send it on down the stack
IoCallDriver(ObjExt->NextLowerDeviceObject, Irp);
break;
case IRP_MN_SURPRISE_REMOVAL:
NTStatus = STATUS_SUCCESS;
Irp->IoStatus.Status = NTStatus;
IoSkipCurrentIrpStackLocation(Irp); //send it on down the stack
IoCallDriver(ObjExt->NextLowerDeviceObject, Irp);
break;
case IRP_MN_DEVICE_USAGE_NOTIFICATION:
NTStatus = STATUS_UNSUCCESSFUL;
Irp->IoStatus.Status = NTStatus;
IoSkipCurrentIrpStackLocation(Irp); //send it on down the stack
IoCallDriver(ObjExt->NextLowerDeviceObject, Irp);
break;
case 8:
case 0xFF:
case IRP_MN_QUERY_LEGACY_BUS_INFORMATION:
NTStatus = STATUS_UNSUCCESSFUL;
Irp->IoStatus.Status = NTStatus;
IoSkipCurrentIrpStackLocation(Irp); //send it on down the stack
IoCallDriver(ObjExt->NextLowerDeviceObject, Irp);
break;
default:
NTStatus = STATUS_UNSUCCESSFUL;
Irp->IoStatus.Status = NTStatus;
IoSkipCurrentIrpStackLocation(Irp); //send it on down the stack
IoCallDriver(ObjExt->NextLowerDeviceObject, Irp);
break;
}
// Debug exit point
//DbgPrint("[PCIDP]->Leaving DispatchPnp, status=0x%x...\n", NTStatus); //debug
//DbgBreakPoint(); //debug
return NTStatus;
}
// ----------------------------------------------------------------------------
// PCIDPDeviceControl. Called by the Windows 2000 I/O system to perform a
// device I/O control function.
// ----------------------------------------------------------------------------
NTSTATUS PCIDPDeviceControl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
){
PIO_STACK_LOCATION IrpStack;
PVOID IoBuffer;
ULONG InputBufferLength;
ULONG OutputBufferLength;
NTSTATUS NTStatus;
// Debug entry point
//DbgPrint("[PCIDP]->Entering DeviceControl...\n"); //debug
//DbgBreakPoint(); //debug
// Initialize the return values with some defaults.
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
// Get a pointer to the current location in the Irp. This is where
// the function codes and parameters are located.
IrpStack = IoGetCurrentIrpStackLocation(IN Irp);
// Get the pointer to the input/output buffer and it's length(s).
IoBuffer = Irp->AssociatedIrp.SystemBuffer;
InputBufferLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
OutputBufferLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
// Determine which I/O control code was specified.
switch (IrpStack->Parameters.DeviceIoControl.IoControlCode){
case IOCTL_PCIDP00_MAP_BASE_REGS:
PCIDPMapBaseRegs(
IN DeviceObject,
IN OUT Irp,
IN OUT IoBuffer,
IN InputBufferLength,
IN OutputBufferLength
);
break;
case IOCTL_PCIDP00_UNMAP:
PCIDPUnMap(
IN DeviceObject,
IN OUT Irp,
IN IoBuffer,
IN InputBufferLength
);
break;
case IOCTL_PCIDP00_MAP_DMA_MEM:
PCIDPMapDMAMem(
IN DeviceObject,
IN OUT Irp,
OUT IoBuffer,
IN OutputBufferLength
);
break;
case IOCTL_PCIDP00_CANCEL_MAP_DMA:
PCIDPCancelMapDMA(
IN DeviceObject,
IN OUT Irp,
IN IoBuffer,
IN InputBufferLength
);
break;
case IOCTL_PCIDP00_UNMAP_DMA:
PCIDPUnMapDMA(
IN DeviceObject,
IN OUT Irp,
IN IoBuffer,
IN InputBufferLength
);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -