📄 pcidppublic.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 PCIDPPublic.c. It contains those PCIDP kernel routines published
// for use by an application using the IoDeviceControl system service.
#include "PCIDPInc.h"
#include "PCIDP.h"
// ----------------------------------------------------------------------------
// PCIDPGetDriverVersion
// ----------------------------------------------------------------------------
VOID PCIDPGetDriverVersion(
IN OUT PIRP Irp,
OUT PVOID IoBuffer,
IN ULONG OutputBufferLength
){
// Define variables.
NTSTATUS NTStatus;
PPCIDP00_GET_VERSION_RECV IoOutput;
// Initialize variables.
IoOutput = (PPCIDP00_GET_VERSION_RECV)IoBuffer;
// Check for adequate output buffer space.
if(OutputBufferLength >= sizeof(PCIDP00_GET_VERSION_RECV)){
NTStatus = STATUS_SUCCESS;
IoOutput->Version = 0x20020822;
Irp->IoStatus.Information = sizeof(PCIDP00_GET_VERSION_RECV);
}
else
NTStatus = STATUS_INVALID_BUFFER_SIZE;
Irp->IoStatus.Status = NTStatus;
}
// ----------------------------------------------------------------------------
// PDIDPMapBaseRegs
// ----------------------------------------------------------------------------
VOID PCIDPMapBaseRegs(
IN PDEVICE_OBJECT DeviceObject,
IN OUT PIRP Irp,
IN OUT PVOID IoBuffer,
IN ULONG InputBufferLength,
IN ULONG OutputBufferLength
){
// Define variables.
//ULONG PCIAddress;
ULONG Length;
ULONG LengthOut;
//ULONG BusNumber;
ULONG VirtualAddress;
//ULONG MappedLength;
//ULONG MapIndex;
UNICODE_STRING PhysicalMemoryUnicodeString;
OBJECT_ATTRIBUTES ObjectAttributes;
//BOOLEAN HALStatus;
//PHYSICAL_ADDRESS LongLength;
//PHYSICAL_ADDRESS FullPCIAddress;
//PHYSICAL_ADDRESS FullPCIAddressEnd;
//PHYSICAL_ADDRESS FullLogicalAddress;
//PHYSICAL_ADDRESS FullLogicalAddressEnd;
PHYSICAL_ADDRESS SectionOffset;
NTSTATUS NTStatus;
HANDLE PhysicalMemoryHandle;
PVOID PhysicalMemorySection;
ULONG MemorySpace;
ULONG MemorySpaceEnd;
PPCIDP00_MAP_BASE_REGS_SEND IoInput;
PPCIDP00_MAP_BASE_REGS_RECV IoOutput;
PPCIDP_EXTENSION ObjExt;
// Initialize variables.
NTStatus = STATUS_SUCCESS;
PhysicalMemoryHandle = NULL;
PhysicalMemorySection = NULL;
MemorySpace = 0;
MemorySpaceEnd = 0;
IoInput = (PPCIDP00_MAP_BASE_REGS_SEND)IoBuffer;
IoOutput = (PPCIDP00_MAP_BASE_REGS_RECV)IoBuffer;
ObjExt = (PPCIDP_EXTENSION)DeviceObject->DeviceExtension;
// Make sure the buffer lengths are of sufficient size to handle
// the transactions.
if((InputBufferLength < sizeof(PCIDP00_MAP_BASE_REGS_SEND)) ||
(OutputBufferLength < sizeof(PCIDP00_MAP_BASE_REGS_RECV))){
NTStatus = STATUS_INVALID_BUFFER_SIZE;
goto ExitA;
}
// Check for a valid Base Address Register index and that its value
// is zero or one, currently, the only supported registers.
if(IoInput->RegNumber > 1){
NTStatus = STATUS_INVALID_PARAMETER;
goto ExitA;
}
// First check to see if the address is for I/O space. If it is, we
// can't map it. Just return the I/O Address so the application can
// use an I/O access driver to read and write from this space.
if(IoInput->RegNumber == 1){
IoOutput->IOSpace = 1;
IoOutput->Length = ObjExt->IOAccessLength;
IoOutput->Address = (ULONG)ObjExt->IOAccess.LowPart;
Irp->IoStatus.Information = sizeof(PCIDP00_MAP_BASE_REGS_RECV);
goto ExitA;
}
// Create the full path name for the physical memory object.
RtlInitUnicodeString(
IN &PhysicalMemoryUnicodeString,
IN L"\\Device\\PhysicalMemory"
);
// Initialize the physical memory object attributes.
InitializeObjectAttributes(
OUT &ObjectAttributes, // Object attributes structure
IN &PhysicalMemoryUnicodeString, // Full path name of the object
IN OBJ_CASE_INSENSITIVE, // Object attribute
IN (HANDLE) NULL, // Root directory is N/A
IN (PSECURITY_DESCRIPTOR) NULL // Security descriptor is N/A
);
// Get a handle to the physical memory object.
NTStatus = ZwOpenSection(
OUT &PhysicalMemoryHandle, // Handle to the physical memory object
IN SECTION_ALL_ACCESS, // Allow full access to the memory
IN &ObjectAttributes // Object attributes structure
);
if(NTStatus != STATUS_SUCCESS) goto ExitA;
// Validate access on the object's handle and get a pointer to the object's
// body.
NTStatus = ObReferenceObjectByHandle(
IN PhysicalMemoryHandle,
IN SECTION_ALL_ACCESS,
IN (POBJECT_TYPE) NULL,
IN KernelMode,
OUT &PhysicalMemorySection,
OUT (POBJECT_HANDLE_INFORMATION) NULL
);
if(NTStatus != STATUS_SUCCESS) goto ExitB;
// Translate the address from a PCI address to a system logical address.
// Initialize the PCI full physical addresses that will be translated.
//FullPCIAddress.HighPart = 0;
//FullPCIAddress.LowPart = ObjExt->BaseAddresses[IoInput->RegNumber];
//FullPCIAddressEnd = RtlLargeIntegerAdd (
// IN FullPCIAddress,
// IN RtlConvertUlongToLargeInteger(IoInput->Length)
//);
// Translate the full PCI physical addresses into corresponding full system
// logical addresses.
//NTStatus = STATUS_ACCESS_DENIED;
//HALStatus = HalTranslateBusAddress(
// IN PCIBus, // bus type
// IN ObjExt->BusNumber, // bus number
// IN FullPCIAddress, // bus address
// IN &MemorySpace, // I/O or memory space
// OUT &FullLogicalAddress // system logical address
//);
//if(HALStatus == FALSE) goto ExitB;
//HALStatus = HalTranslateBusAddress(
// IN PCIBus, // bus type
// IN ObjExt->BusNumber, // bus number
// IN FullPCIAddressEnd, // bus address
// IN &MemorySpaceEnd, // I/O or memory space
// OUT &FullLogicalAddressEnd // system logical address
//);
// if(HALStatus == FALSE) goto ExitB;
// Calculate the length of the memory to be mapped.
//LongLength = RtlLargeIntegerSubtract(
// IN FullLogicalAddressEnd,
// IN FullLogicalAddress
//);
//Length = LongLength.LowPart;
//LengthOut = LongLength.LowPart;
Length = ObjExt->MemoryAccessLength;
LengthOut = ObjExt->MemoryAccessLength;
// Now map the system logical address in this process' virtual address
// space.
VirtualAddress = 0;
//SectionOffset = FullLogicalAddress;
SectionOffset = ObjExt->MemoryAccess;
NTStatus = ZwMapViewOfSection(
IN PhysicalMemoryHandle, //section handle
IN (HANDLE) -1, //process handle
IN OUT (PVOID*)&VirtualAddress, //base address (virtual address)
IN 0L, //zero bits
IN Length, //commit size
IN OUT &SectionOffset, //section offset
IN OUT &LengthOut, //view size
IN ViewShare, //inherit disposition (0)
IN 0, //allocation type
IN PAGE_READWRITE | PAGE_NOCACHE //protect
);
// Mapping the section above rounded the logical address down to
// the nearest 64 K boundary. Now return a virtual address pointing
// to our request area by adding in the offset from the beginning
// of the section.
if(NTStatus == STATUS_SUCCESS){
IoOutput->IOSpace = 0;
//IoOutput->Address = VirtualAddress +
// ((ULONG)FullLogicalAddress.LowPart - (ULONG)SectionOffset.LowPart);
//IoOutput->Length = LengthOut -
// ((ULONG)FullLogicalAddress.LowPart - (ULONG)SectionOffset.LowPart);
IoOutput->Address = VirtualAddress +
((ULONG)ObjExt->MemoryAccess.LowPart - (ULONG)SectionOffset.LowPart);
IoOutput->Length = LengthOut -
((ULONG)ObjExt->MemoryAccess.LowPart - (ULONG)SectionOffset.LowPart);
Irp->IoStatus.Information = sizeof(PCIDP00_MAP_BASE_REGS_RECV);
}
ExitB:
ZwClose(PhysicalMemoryHandle);
ExitA:
Irp->IoStatus.Status = NTStatus;
}
// ----------------------------------------------------------------------------
// PCIDPUnMap unmaps a region of virtual memory from physical memory
// that was mapped earlier using the PCIDPMapBaseRegs routines.
// ----------------------------------------------------------------------------
VOID PCIDPUnMap(
IN PDEVICE_OBJECT DeviceObject,
IN OUT PIRP Irp,
IN PVOID IoBuffer,
IN ULONG InputBufferLength
){
// Define variables.
ULONG i;
NTSTATUS NTStatus;
PPCIDP00_UNMAP_SEND IoInput;
PPCIDP_EXTENSION ObjExt;
// Initialize variables.
NTStatus = STATUS_SUCCESS;
IoInput = (PPCIDP00_UNMAP_SEND)IoBuffer;
ObjExt = (PPCIDP_EXTENSION)DeviceObject->DeviceExtension;
if(InputBufferLength >= sizeof(PCIDP00_UNMAP_SEND)){
// Don't try to unmap from I/O space but it's not a failure either.
// Do unmap from memory space.
if(IoInput->VirtualAddress != (ULONG)ObjExt->IOAccess.LowPart){
NTStatus = ZwUnmapViewOfSection(
IN (HANDLE) -1,
IN (PVOID)IoInput->VirtualAddress
);
}
}
else
NTStatus = STATUS_INVALID_BUFFER_SIZE;
Irp->IoStatus.Status = NTStatus;
}
// ----------------------------------------------------------------------------
// PDIDPMapDMAMem
// ----------------------------------------------------------------------------
VOID PCIDPMapDMAMem(
IN PDEVICE_OBJECT DeviceObject,
IN OUT PIRP Irp,
OUT PVOID IoBuffer,
IN ULONG OutputBufferLength
){
NTSTATUS NTStatus;
PPCIDP00_MAP_DMA_MEM_RECV IoOutput;
PPCIDP_EXTENSION ObjExt;
// Initialize variables.
IoOutput = (PPCIDP00_MAP_DMA_MEM_RECV)IoBuffer;
ObjExt = (PPCIDP_EXTENSION)DeviceObject->DeviceExtension;
if(OutputBufferLength >= sizeof(PCIDP00_MAP_DMA_MEM_RECV)){
if(ObjExt->MDL){
IoOutput->LinearAddress = (unsigned long)MmMapLockedPages(
ObjExt->MDL,
UserMode
);
if(IoOutput->LinearAddress != 0){
IoOutput->PhysicalAddress = ObjExt->PhysicalDMAAddress;
Irp->IoStatus.Information = sizeof(PCIDP00_MAP_DMA_MEM_RECV);
NTStatus = STATUS_SUCCESS;
}
else
NTStatus = STATUS_NO_MEMORY;
}
else
NTStatus = STATUS_NO_MEMORY;
}
else
NTStatus = STATUS_INVALID_BUFFER_SIZE;
Irp->IoStatus.Status = NTStatus;
}
// ----------------------------------------------------------------------------
// PCIDPCancelMapDMA
// ----------------------------------------------------------------------------
VOID PCIDPCancelMapDMA(
IN PDEVICE_OBJECT DeviceObject,
IN OUT PIRP Irp,
IN PVOID IoBuffer,
IN ULONG InputBufferLength
){
KIRQL CancelSpin;
PPCIDP00_UNMAP_DMA_SEND IoInput;
PPCIDP_EXTENSION ObjExt;
PLINKED_LIST LLEntry;
NTSTATUS NTStatus;
// Initialize variables.
IoInput = (PPCIDP00_UNMAP_DMA_SEND)IoBuffer;
ObjExt = (PPCIDP_EXTENSION)DeviceObject->DeviceExtension;
//ObjExt->MemoryBase[0x1C5E]++; //debug
// Get an empty linked list entry.
LLEntry = GetFreeEntry(ObjExt);
if(LLEntry != NULL){
// Set up a cancel routine that unmaps the DMA should the application fail
// to do so.
IoMarkIrpPending (Irp);
IoAcquireCancelSpinLock (&CancelSpin);
IoSetCancelRoutine (Irp, PCIDPCancelMapDMARoutine);
IoReleaseCancelSpinLock (CancelSpin);
// Add this IRP to the linked list
// Save the linear address required to unmap DMA memory in Type.
LLEntry->RegisteredInterrupt.Irp = Irp;
LLEntry->RegisteredInterrupt.Type = (ULONG)IoInput->LinearAddress;
InsertEntry(ObjExt, LLEntry);
//ObjExt->MemoryBase[0x1C5F]++; //debug
//ObjExt->MemoryBase[0x1C60] = (ULONG)IoInput->LinearAddress; //debug
// Return with I/O pending.
NTStatus = STATUS_PENDING;
}
else
NTStatus = STATUS_NO_MEMORY;
// Return with current status.
Irp->IoStatus.Status = NTStatus;
}
// ----------------------------------------------------------------------------
// PDIDPUnMapDMA
// ----------------------------------------------------------------------------
VOID PCIDPUnMapDMA(
IN PDEVICE_OBJECT DeviceObject,
IN OUT PIRP Irp,
IN PVOID IoBuffer,
IN ULONG InputBufferLength
){
// Define variables.
ULONG i;
NTSTATUS NTStatus;
PPCIDP00_UNMAP_DMA_SEND IoInput;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -