Hi Tim, All,
The code used to allocate the buffer is:
NTSTATUS AllocateContinuousPhysicalMemory (IN PDEVICE_EXTENSION DevExt,int Channel)
{
ULONG NumberOfMapRegisters;
DEVICE_DESCRIPTION DeviceDescription;
PHYSICAL_ADDRESS LogicalAddress;
PDMA_ADAPTER DmaAdapter;
PDEVICE_OBJECT FdoData;
PALLOCATE_COMMON_BUFFER AllocateCommonBuffer;
PVOID UserSpaceAddress;
PAGED_CODE();
RtlZeroMemory(&DeviceDescription, sizeof(DEVICE_DESCRIPTION));
#if defined(DMA_VER2)
DeviceDescription.Version = DEVICE_DESCRIPTION_VERSION2;
#else
DeviceDescription.Version = DEVICE_DESCRIPTION_VERSION;
#endif
DeviceDescription.Master = TRUE;
DeviceDescription.ScatterGather = FALSE;
DeviceDescription.Dma32BitAddresses = TRUE;
DeviceDescription.Dma64BitAddresses = FALSE;
DeviceDescription.InterfaceType = PCIBus;
DeviceDescription.MaximumLength = COMMON_BUFFER_SIZE;
FdoData = WdfDeviceWdmGetPhysicalDevice(DevExt->Device);
DmaAdapter = IoGetDmaAdapter(FdoData,&DeviceDescription,&NumberOfMapRegisters);
if (!DmaAdapter)
{
KdPrint ((“IoGetDmaAdapter failed.\n”));
return STATUS_INSUFFICIENT_RESOURCES;
}
AllocateCommonBuffer = DmaAdapter->DmaOperations->AllocateCommonBuffer;
if (!AllocateCommonBuffer)
{
KdPrint ((“devExt->AllocateCommonBuffer=0x0\n”));
return STATUS_INSUFFICIENT_RESOURCES;
}
//Allocate common buffer and return its kernel virtual address
DevExt->KernelCommonBuffer[Channel] = AllocateCommonBuffer(DmaAdapter,
COMMON_BUFFER_SIZE,
&LogicalAddress,
FALSE);
if (!DevExt->KernelCommonBuffer)
{
KdPrint ((“AllocateCommonBuffer failed.\n”));
return STATUS_INSUFFICIENT_RESOURCES;
}
//RtlZeroMemory(DevExt->KernelCommonBuffer[Channel], COMMON_BUFFER_SIZE);
RtlFillMemory (DevExt->KernelCommonBuffer[Channel], COMMON_BUFFER_SIZE, 0xAA);
DevExt->CommonBufferMdl[Channel] = IoAllocateMdl (DevExt->KernelCommonBuffer[Channel],COMMON_BUFFER_SIZE,FALSE, FALSE, NULL);
if (!DevExt->CommonBufferMdl)
{
KdPrint ((“IoAllocateMdl failed.\n”));
return STATUS_INSUFFICIENT_RESOURCES;
}
MmBuildMdlForNonPagedPool (DevExt->CommonBufferMdl[Channel]);
/*DevExt->PhysicalKernelCommonBuffer[Channel] = MmGetPhysicalAddress (DevExt->KernelCommonBuffer[Channel]);*/
DevExt->PhysicalKernelCommonBuffer[Channel] = LogicalAddress;
return STATUS_SUCCESS;
}
The code that handles the IOCTL request to map this buffer is:
BOOLEAN
RequestDispatchToSequentialQueue(
__in WDFDEVICE Device,
__in WDFREQUEST Request,
__in WDF_REQUEST_PARAMETERS RequestParameters
)
/*++
Routine Description:
These requests can be processed in a non-serialized manner, most of them don’t need to access device.
Arguments:
Device - handle to a WDF Device object
Request - handle to the incoming WDF Request object
RequestParameters - request parameters
Return Value:
BOOLEAN - TRUE (request processed); FALSE (request is not processed in this function).
–*/
{
NTSTATUS status = STATUS_SUCCESS;
size_t dataLength = 0;
PDEVICE_EXTENSION devExt = NULL;
MODULE_ALLOCATE_COMMON_BUFFER *pAllocateRequest;
MODULE_ALLOCATE_COMMON_BUFFER_REPLY *pAllocateReply;
MODULE_DEALLOCATE_COMMON_BUFFER *pDeAllocateRequest;
WDFREQUEST InternalRequest;
WDFREQUEST DpcRequest;
PMDL CommonBufferMdl;
PVOID CommonBufferVirtualAddress;
ULONG CommonBufferLength;
PUCHAR pDst;
ULONG PciAddress;
ULONG Offset;
ULONG PhysicalDataAddress;
size_t bytesReturned = 0;
void *pInBuffer;
void *pOutBuffer;
int Channel;
size_t Length;
ULONG IoControlCode = RequestParameters.Parameters.DeviceIoControl.IoControlCode;
devExt = PLxGetDeviceContext(Device);
switch (IoControlCode)
{
case MODULE_ALLOCATE_COMMON_BUFFER_CODE:
KdPrint ((“PsGetCurrentProcessId=%x\n”,PsGetCurrentProcessId()));
status = WdfRequestRetrieveInputBuffer (Request,sizeof(MODULE_ALLOCATE_COMMON_BUFFER),
&pInBuffer, &Length);
pAllocateRequest = (MODULE_ALLOCATE_COMMON_BUFFER *)pInBuffer;
Channel = pAllocateRequest->Channel;
status = WdfRequestRetrieveOutputBuffer (Request,sizeof(MODULE_READ_LONG_REPLY),
&pOutBuffer, &Length);
pAllocateReply = (MODULE_ALLOCATE_COMMON_BUFFER_REPLY *)pOutBuffer;
bytesReturned = sizeof(MODULE_ALLOCATE_COMMON_BUFFER_REPLY);
//Map common buffer to user space. This can be done only upon IOCTL request
__try
{
devExt->UserSpaceCommonBuffer[Channel] = MmMapLockedPagesSpecifyCache(devExt->CommonBufferMdl[Channel],
UserMode,
MmCached ,
NULL,
FALSE,
NormalPagePriority);
if (!devExt->UserSpaceCommonBuffer)
{
KdPrint ((“MmMapLockedPagesSpecifyCache failed.\n”));
}
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
devExt->UserSpaceCommonBuffer[Channel] = NULL;
KdPrint ((“MmMapLockedPagesSpecifyCache caused exception: %x\n”,GetExceptionCode()));
}
pAllocateReply->Address = (UINT64)devExt->UserSpaceCommonBuffer[Channel];
WdfRequestCompleteWithInformation (Request,STATUS_SUCCESS,bytesReturned);
break;
case MODULE_DEALLOCATE_COMMON_BUFFER_CODE:
status = WdfRequestRetrieveInputBuffer (Request,sizeof(MODULE_DEALLOCATE_COMMON_BUFFER),
&pInBuffer, &Length);
pDeAllocateRequest = (MODULE_DEALLOCATE_COMMON_BUFFER *)pInBuffer;
Channel = pDeAllocateRequest->Channel;
__try
{
MmUnmapLockedPages (devExt->UserSpaceCommonBuffer[Channel], devExt->CommonBufferMdl[Channel]);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
KdPrint ((“MmUnmapLockedPages caused exception: %x\n”,GetExceptionCode()));
}
bytesReturned = 0;
WdfRequestCompleteWithInformation (Request,STATUS_SUCCESS,bytesReturned);
break;
default:
return FALSE; //The IOCTL code will be handled in the default IoControl handler
}
return TRUE; //This will mark the request as processed
}
VOID DeviceEvtIoInCallerContext (__in WDFDEVICE Device,
__in WDFREQUEST Request)
/*++
Routine Description:
Responds to EvtIoInCallerContext events from KMDF
It calls different functions to process different type of IOCTLs.
Arguments:
Device - handle to a WDF Device object
Request - handle to the incoming WDF Request object
Return Value:
VOID.
–*/
{
NTSTATUS status = STATUS_SUCCESS;
PDEVICE_EXTENSION devExt = NULL;
WDF_REQUEST_PARAMETERS requestParameters;
BOOLEAN processed = FALSE;
WdfRequestGetParameters(Request, &requestParameters);
//KdPrint ((“–>DeviceEvtIoInCallerContext\n”));
devExt = PLxGetDeviceContext(Device);
// get the request parameters
WDF_REQUEST_PARAMETERS_INIT(&requestParameters);
WdfRequestGetParameters(Request, &requestParameters);
if (requestParameters.Type == WdfRequestTypeDeviceControl)
{
//KdPrint ((“IoControlCode=0x%08x\n”,requestParameters.Parameters.DeviceIoControl.IoControlCode));
// 1. Requests that should be processed only in the context of the app’s process
if (!processed)
{
processed = RequestDispatchToSequentialQueue(Device, Request, requestParameters);
}
if (!processed)
{
//KdPrint ((“Forwarding to default IOCTL\n”));
status = WdfDeviceEnqueueRequest(Device, Request);
if (!NT_SUCCESS(status))
{
KdPrint ((“WdfDeviceEnqueueRequest failed\n”));
}
}
}
//KdPrint ((“<–DeviceEvtIoInCallerContext\n”));
}
I did not attach the code that handles regular IOCTL request or the BARs allocation.
Thank you,
Zvika