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!

Re: IRQL He11 by Don

Don
Wed Aug 02 19:02:34 CDT 2006

You can call RtlCopyMemory from any IRQL as long as both buffers are
non-paged. You should not be building a MDL for this, just allocate the
memory from NonPagedPool. Of course depending on the frequency of DMA
operations, you could also just queue a work item and have it write the data
from the DMA buffer.


--
Don Burn (MVP, Windows DDK)
Windows 2k/XP/2k3 Filesystem and Driver Consulting
http://www.windrvr.com
Remove StopSpam from the email to reply



"Slide-O-Mix" <SlideOMix@discussions.microsoft.com> wrote in message
news:AC6A0D46-DBAA-43C7-8D71-BE7C08DC6C97@microsoft.com...
>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!
>
>
>
>



Re: IRQL He11 by SlideOMix

SlideOMix
Wed Aug 02 22:31:01 CDT 2006

Ok, that makes sense, I am allocating one of the buffers from the
NonPagedPool as can be seen from my code. The other is being allocated using
AllocateCommonBuffer on a DMA adapter, is there anything special I need to do
for that buffer? I think that might be where my BSOD's are coming from in
relation to the IRQL not less than or equal errors I am seeing.

"Don Burn" wrote:

> You can call RtlCopyMemory from any IRQL as long as both buffers are
> non-paged. You should not be building a MDL for this, just allocate the
> memory from NonPagedPool. Of course depending on the frequency of DMA
> operations, you could also just queue a work item and have it write the data
> from the DMA buffer.
>
>
> --
> Don Burn (MVP, Windows DDK)
> Windows 2k/XP/2k3 Filesystem and Driver Consulting
> http://www.windrvr.com
> Remove StopSpam from the email to reply
>
>
>
> "Slide-O-Mix" <SlideOMix@discussions.microsoft.com> wrote in message
> news:AC6A0D46-DBAA-43C7-8D71-BE7C08DC6C97@microsoft.com...
> >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!
> >
> >
> >
> >
>
>
>

RE: IRQL He11 by pavel_a

pavel_a
Thu Aug 03 06:47:02 CDT 2006

"Slide-O-Mix" wrote:
...................
> try
> {
> RtlZeroMemory(pWriteCtx->pBuffer, pBuffer->Size);
> pWriteCtx->bufferSize = pBuffer->Size;
..........

Not sure that try & exception handlers work in a DPC for ISR...
--PA


RE: IRQL He11 by SlideOMix

SlideOMix
Thu Aug 03 07:18:02 CDT 2006



"Pavel A." wrote:

> "Slide-O-Mix" wrote:
> ...................
> > try
> > {
> > RtlZeroMemory(pWriteCtx->pBuffer, pBuffer->Size);
> > pWriteCtx->bufferSize = pBuffer->Size;
> ..........
>
> Not sure that try & exception handlers work in a DPC for ISR...
> --PA
>


You are correct, they don't :)

I did finally get this all working better, I looked through the code and
noticed that during the allocation of the common buffer for DMA it goes
through all the steps to create an Mdl Safe address, I just switched to using
that address during RtlCopyMemory and it works much better. Thanks all for
the help.