I am currently modifying a driver we use internally that interfaces with a
PCI board. We are adding a DMA capability to the board where we can DMA data
to and from specific memory regions, that is working correctly and I get
interrupts and get into my DpcForIsr, etc, BUT what I need to do when I get
data from the DMA is write it out to a file. Now, I know that in my Dpc I
can't call ZwWriteFile to write out to my file that I opened previously, so I
wrote code to setup a work item to do it for me. I am trying to copy the data
from the NonPagedPool physical memory that the DMA is going into to another
buffer that the work item can use to write to the file. I am having major
issues because obviously RtlCopyMemory can't be called in the Dpc either
because the IRQL is wrong. I tried getting an MDL and locking the pages in
memory so they are resident before calling RtlCopyMemory, but I am having a
heck of a time. If anyone can help out I would appreciate it greatly, below
is the portion of the code that I am having problems with, it is contained in
a DpcForIsr.
// allocate a work item context
pWriteCtx = (PWRITECTX_INFO) ExAllocatePoolWithTag(
NonPagedPool,
sizeof(WRITECTX_INFO),
'xtcW'
);
// assign file handle
pWriteCtx->hFile = pDmaStream->hFile;
pWriteCtx->pBuffer = (U32*)ExAllocatePoolWithTag(
NonPagedPool,
pBuffer->Size,
'Wmem'
);
if(pWriteCtx->pBuffer == NULL)
{
DebugPrintf((
"Insufficient resources to allocate work queue buffer\n"
));
ExFreePool(pWriteCtx);
}
else
{
try
{
RtlZeroMemory(pWriteCtx->pBuffer, pBuffer->Size);
pWriteCtx->bufferSize = pBuffer->Size;
pMdl = IoAllocateMdl(
pWriteCtx->pBuffer,
pBuffer->Size,
FALSE,
TRUE,
NULL
);
pMdlDma = IoAllocateMdl(
(PVOID)pBuffer->UserAddr,
pBuffer->Size,
FALSE,
TRUE,
NULL
);
MmBuildMdlForNonPagedPool(
pMdl
);
MmBuildMdlForNonPagedPool(
pMdlDma
);
MmProbeAndLockPages(
pMdl,
KernelMode,
IoWriteAccess
);
MmProbeAndLockPages(
pMdlDma,
KernelMode,
IoReadAccess
);
//
// Map the physical pages described by the MDL into system space.
// Note: double mapping the buffer this way causes lot of
// system overhead for large size buffers.
//
pTempBuf = MmGetSystemAddressForMdlSafe(
pMdl,
NormalPagePriority
);
pTempDmaBuf = MmGetSystemAddressForMdlSafe(
pMdlDma,
NormalPagePriority
);
// copy the data from the buffer into the work queue buffer
RtlCopyMemory(
(VOID*)pTempBuf,
(VOID*)pTempDmaBuf,
pBuffer->Size
);
// unlock the pages and free the MDL
MmUnlockPages(
pMdl
);
MmUnlockPages(
pMdlDma
);
IoFreeMdl(
pMdl
);
IoFreeMdl(
pMdlDma
);
pBuffer is the buffer that represents the DMA buffer where the data from the
DMA is located. My work item context structure looks like this:
typedef struct _WRITECTX_INFO
{
PIO_WORKITEM item;
DEVICE_EXTENSION *pdx;
U32* pBuffer;
U32 bufferSize;
HANDLE hFile;
} WRITECTX_INFO, *PWRITECTX_INFO;
I am very new to driver development, so I know I am doing something wrong
(obviously or it would be working). Thanks!