WDM DMA Question

WDM DMA Question

Post by Chris Edgingto » Thu, 15 May 2003 06:16:36



I have a WDM driver for a custom PCI device. I'm debugging this driver
on WinXPSP1. The driver needs to do DMA operations on the device. The
device is a busmaster that does scatter gather. Right now we're just at
the "prove this is possible" stage.

The goal is to create an architecture whereby our application and our
driver can share a very large (512k) buffer. The WDM driver, when
notified via IOCTL, would continuously DMA data from its data-capture
logic into the shared buffer. The application would continuously monitor
/ analyze / display the data coming into this buffer. When in
"continous" mode, there'd be no communication between the app and the
driver to indicate DMA done or anything like that - the app just knows
that the driver is constantly DMA'ing more data into the buffer.

If we allocate common DMA buffers in the driver and use them to do the
DMA (we're just DMA'ing dummy data embedded in the driver right now),
the DMA works. However, we cannot (and likely would not want to)
allocate common DMA buffers of the size we need.

If we allocate general buffers from the non-paged pool, then use
GetScatterGatherList, as documented, the SCATTER_GATHER_LIST we get back
does not seem to be correct. In fact, programming the hardware with the
values in the list results in the hardware claiming that the DMA has
happened, but definitely not into our buffers (and likely trashing
something else).

As an example, one of the buffers we get from the non-paged pool has a
virtual address of 0x84B0F4F8. Using the Softice PAGE command I can see
that this maps to a physical address of 0x04C924F8. However, the
PHYSICAL_ADDRESS returned in the SGLIST has HighPart=0x80D and
LowPart=0xB70E04F8.

My questions are:

Is this a valid process?

Does GetScatterGatherList require that the MDL provided be one that came
through an IRP?

Is there a "right" way to accomplish what I've described? (I've got Oney
2nd Ed if you want to refer me to something in there .... been through
much of it already, but might have missed something.)

Any other thoughts you can provide that might help?

Thanks,
-Chris

 
 
 

WDM DMA Question

Post by Chris Edgingto » Thu, 15 May 2003 06:23:38


One point I forgot to mention. If I actually use the physical addresses
that I determined using Softice (instead of the addresses returned in
the SGLIST), then the DMA transfers work properly (we see the data go
into the proper memory locations).

Thanks,
-Chris

 
 
 

WDM DMA Question

Post by Maxim S. Shatski » Thu, 15 May 2003 21:51:36


Quote:> The goal is to create an architecture whereby our application and
our
> driver can share a very large (512k) buffer. The WDM driver, when
> notified via IOCTL, would continuously DMA data from its
data-capture
> logic into the shared buffer. The application would continuously
monitor
> / analyze / display the data coming into this buffer. When in
> "continous" mode, there'd be no communication between the app and
the
> driver to indicate DMA done or anything like that - the app just

knows

Better idea:
- allocate lots of buffers in the app
- send lots of overlapped ReadFile to the driver
- in the driver, use the MDL from the IRP for DMA
- in the app, ReadFile completion routine will deliver the buffer with
the filled data to the rest of the app's code.

    Max

 
 
 

WDM DMA Question

Post by Chris Edgingto » Fri, 16 May 2003 01:27:19


But why would this be "better"? It looks like a lot more work in the
app, and a lot more CPU involvement.

-Chris

Quote:> Better idea:
> - allocate lots of buffers in the app
> - send lots of overlapped ReadFile to the driver
> - in the driver, use the MDL from the IRP for DMA
> - in the app, ReadFile completion routine will deliver the buffer with
> the filled data to the rest of the app's code.

>     Max

 
 
 

WDM DMA Question

Post by Maxim S. Shatski » Sat, 17 May 2003 01:40:28


But much lesser work in the driver, and no subtle sync issues at all.
ReadFiles is not much more code in the app, then the subtle sync stuff
you suggested.

    Max


Quote:> But why would this be "better"? It looks like a lot more work in the
> app, and a lot more CPU involvement.

> -Chris

> > Better idea:
> > - allocate lots of buffers in the app
> > - send lots of overlapped ReadFile to the driver
> > - in the driver, use the MDL from the IRP for DMA
> > - in the app, ReadFile completion routine will deliver the buffer
with
> > the filled data to the rest of the app's code.

> >     Max

 
 
 

WDM DMA Question

Post by David » Sat, 17 May 2003 08:40:19


Quote:> that this maps to a physical address of 0x04C924F8. However, the
> PHYSICAL_ADDRESS returned in the SGLIST has HighPart=0x80D and
> LowPart=0xB70E04F8.

I have also seen GetSGL() return bogus PAs.  Try modifying your call
to IoGetDmaAdapter() by setting DeviceDescription.MaximumLength =
0xFFFFFFFF;  Unless your machine has more than 4GB ram, you should
never see PHYSICAL_ADDRESS.HighPart have a value other than zero.
 
 
 

WDM DMA Question

Post by Chris Edgingto » Sat, 17 May 2003 23:45:04


Well, setting MaximumLength to 0xFFFFFFFF didn't solve the problem - I'm
still getting bogus values. I'm going to spend some time today tracing
into GSGL to see if anything obvious is happening.

Thanks,
-Chris


>>that this maps to a physical address of 0x04C924F8. However, the
>>PHYSICAL_ADDRESS returned in the SGLIST has HighPart=0x80D and
>>LowPart=0xB70E04F8.

> I have also seen GetSGL() return bogus PAs.  Try modifying your call
> to IoGetDmaAdapter() by setting DeviceDescription.MaximumLength =
> 0xFFFFFFFF;  Unless your machine has more than 4GB ram, you should
> never see PHYSICAL_ADDRESS.HighPart have a value other than zero.

 
 
 

WDM DMA Question

Post by David » Sun, 18 May 2003 06:09:07


One other thought... make sure your MDL is "filled in".  If the MDL is
not describing the physical pages then GetSGL() will return junk.  If
you are using non paged pool for your buffer, then your code should
look something like this:

Ptr = ExAllocatePool(nonpaged, size);
Mdl = IoAllocateMdl(Ptr, size, FALSE, FALSE, NULL);
MmBuildMdlForNonPagedPool(Mdl);    /* <---  make sure you do this */

DmaAdapter->
DmaOperations->
GetScatterGatherList(DmaAdapter,
                     Fdo,
                     Mdl,
                     Ptr,
                     size,
                     SglCallbackFunc,
                     context,
                     Direction);

 
 
 

WDM DMA Question

Post by Chris Edgingto » Sun, 18 May 2003 06:09:04


Quote:> As an example, one of the buffers we get from the non-paged pool has a
> virtual address of 0x84B0F4F8. Using the Softice PAGE command I can see
> that this maps to a physical address of 0x04C924F8. However, the
> PHYSICAL_ADDRESS returned in the SGLIST has HighPart=0x80D and
> LowPart=0xB70E04F8.

FAWI ....

Turns out MmBuildMdlForNonPagedPool needed to be called on the Mdl to
get the page table built at the end. That fixed the problem.

-Chris

 
 
 

1. WDM Driver MEM to MEM transfer using PC DMA Channel

Our "device" is a PCI bus card that simply has memory
resources on it (i.e. CmResourceTypeMemory) used for SFRs
and Data Buffers. There are no other resources (i.e. no
DMA, Port, Interrupt, etc.). I have already implemented a
WDM driver that moves data to the memory on the card
(mapped via MmMapIoSpace) using the HAL routines
READ/WRITE_REGISTER_BUFFER_ULONG. This all works great,
but now my company wants me to move the data using a DMA
channel in the PC. I am having trouble figuring out TWO
things:

1) Since our card requests no DMA (or Interrupt) resources
(i.e. none show up in the translated->PartialDescriptors)
I cannot seem to figure out how to establish what
System/PC DMA channel to use, or what interrupt IRQ/Vector
to use, (?normally established by PnP manager?). How do I
determine what DMA channel to place in dd.DmaChannel
before calling IoGetDmaAdapter? Can I just choose a DMA
Channel (i.e. 0,1,2,3,5,6,7) and use it? How do I
determine what IRQ/Vec to use for IoConnectInterrupt call?
(note: I have obtained a few pieces of sample code,
including SLAVEDMA from MSDN, but these all seem to assume
that the PnP manager assigns DMA and Interrupt resources.)

2) After calling DmaOperation->MapTransfer (in my
AdapterControl routine) how do I implement StartTransfer?
(i.e. how do I start the transfer using a System/PC DMA
channel?) The pieces of sample code I have either do
direct i/o to a DMA controller on the device (which we
don't have), or have a StartTransfer STUB routine that
says "Enter Vendor Code Here". Is there some set of DDK
routines I can call here to kick off the transfer, or do I
have to do direct i/o to whatever DMA channel I ended up
selecting?

My ultimate goal is a WDM driver that uses a System/PC DMA
channel to move data between an MDL(or CommonBuffer) and
the "MmMapIoSpace mapped" memory on our "card/device".

2. mode_def for Epson Stylus 800?

3. Implementation of Non WDM and WDM driver

4. Own WWW

5. USB Class Drivers, WDM Drivers and WDM Modems

6. Yamaha or Plextor

7. DMA/33 to DMA/66 transition inquiry

8. PDF to XML

9. How to perform DMA transfer in SCSI miniport driver using system DMA

10. Simple (?) wdm questions.

11. WHQL NDIS-WDM question.

12. question to floating-point calculations in WDM-Drivers

13. Newbie Question: Comvert Win9x driver to WDM?