chained MDLs in XP

I have an application in which one or more user mode threads each supply
one or more circular buffers into which packets of data with a specified
identifier will be dropped. Each circular buffer will only hold packets
of a certain type. The proprietary device supplying the packets only
interrupts the processor after it has X packets to deliver (of any type)
or after Y seconds have elapsed. The device is also capable of bus master
DMA. After my driver receives an interrupt from the device, it proceeds
to identify what packets the device has, building a chained MDL to
transfer the packets’ payloads to their corresponding circular buffers:

NewMdl = IoAllocateMdl (OutBuf, PktDataSize, FALSE, FALSE, NULL);

MmBuildMdlForNonPagedPool (NewMdl);

if ( LastMdl != NULL ) LastMdl->Next = NewMdl;

LastMdl = NewMdl;

where OutBuf is the non-paged system space virtual address of a circular
buffer, offset by zero or more bytes, returned by
MmGetSystemAddressForMdlSafe at the time that a thread identified a
circular buffer to the driver. The IRPs which identify the circular
buffers are still pending at the time that the chained MDL is built.

My question has now to do with the virtual address which I will supply to
GetScatterGatherList: How do I derive this address for the chained MDL?
Do I need to follow the example in src\kernel\agp\agplib\intrface.c, which
creates a single MDL from the chain by merging the arrays of PFNs?

“Roberto Marino” wrote in message
news:xxxxx@ntdev…
>
> My question has now to do with the virtual address which I will supply to
> GetScatterGatherList: How do I derive this address for the chained MDL?
> Do I need to follow the example in src\kernel\agp\agplib\intrface.c, which
> creates a single MDL from the chain by merging the arrays of PFNs?
>

NICE question!

If things work “the way they should”, you should not have to worry about the
VirtualAddress for subsequent MDLs in the chain.

GetScatterGatherList only uses the “CurrentVa” argument to determine the
starting offset for the transfer (and thus, ultimately the length of the
transfer as well). Thus, you can not specify an offset at which to start
the transfer that extends beyond the first MDL in the chain (if you wanted
to skip the entire FIRST MDL in the chanin and offset into the SECOND MDL in
the chain, for example, you would remove the first MDL from the chain).
Likewise, chaining multiple MDLs together implies that you want to start at
some offset into the first MDL, and transfer the entire contents of all the
remaining chained MDLs (up to the max transfer length you specify,
obviously). Note this is analagous to DMA transfers of pages (you start at
some offset into the first page, and transfer only full pages, up to the
maximum transfer length).

The MDL should be treated as an opaque structure (in fact, it’s one of the
very few structures that most of the O/S itself typically treats as opaque
outside of the memory manager). So, merging the arrays of PFNs to build a
sort of mega-MDL is really not a very attractive solution. Stay away from
that approach if possible.

Hope that helps – And please post back and let us know how it goes,

Peter
OSR

Thank you for your reply.

Am I to construe your comment on the MDL being an opaque structure to mean
that I should not even be using the Next pointer in that data structure?
Should I then allocate an IRP and build the chain of MDLs using
IoAllocateMdl with the SecondaryBuffer parameter set to TRUE?

> where OutBuf is the non-paged system space virtual address of a circular

buffer, offset by zero or more bytes, returned by

Can you use AllocateCommonBuffer for a circular buffer? In this case, you do
not need neither MDLs not GetScatterGatherList, since you already have a bus
address of the buffer.

You need IoMapTransfer or GetScatterGatherList only for IRP’s MDLs, not for
driver-allocated memory.

My question has now to do with the virtual address which I will supply to
GetScatterGatherList: How do I derive this address for the chained MDL?

(assuming you need to map the IRP’s MDL)

Use IoMapTransfer instead. The older stuff is usually more reliable :slight_smile:

The VirtualAddress parameter is MmGetMdlVirtualAddress(Mdl).

Maxim Shatskih, Windows DDK MVP
StorageCraft Corporation
xxxxx@storagecraft.com
http://www.storagecraft.com

It is always safe to use the ->Next field in a MDL.

Maxim Shatskih, Windows DDK MVP
StorageCraft Corporation
xxxxx@storagecraft.com
http://www.storagecraft.com

----- Original Message -----
From: “Roberto Marino”
To: “Windows System Software Devs Interest List”
Sent: Tuesday, September 16, 2003 6:18 PM
Subject: [ntdev] Re: chained MDLs in XP

> Thank you for your reply.
>
> Am I to construe your comment on the MDL being an opaque structure to mean
> that I should not even be using the Next pointer in that data structure?
> Should I then allocate an IRP and build the chain of MDLs using
> IoAllocateMdl with the SecondaryBuffer parameter set to TRUE?
>
> —
> Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256
>
> You are currently subscribed to ntdev as: xxxxx@storagecraft.com
> To unsubscribe send a blank email to xxxxx@lists.osr.com

“Maxim S. Shatskih” wrote in message
news:xxxxx@ntdev…
> > where OutBuf is the non-paged system space virtual address of a circular
> > buffer, offset by zero or more bytes, returned by
>
> Can you use AllocateCommonBuffer for a circular buffer? In this case, you
do
> not need neither MDLs not GetScatterGatherList, since you already have a
bus
> address of the buffer.
>
> You need IoMapTransfer or GetScatterGatherList only for IRP’s MDLs, not
for
> driver-allocated memory.
>

Good point. I has assumed the OP was DMAing the data directly from the
user’s address space. On second reading this is not exactly clear.

>
> Use IoMapTransfer instead. The older stuff is usually more reliable :slight_smile:
>

I’m sorry, but that is NOT good advice. The older stuff gets replaced for a
reason. GetScatterGatherList makes lots of things that were in
IoAllocateAdapterChannel/IoMapTransfer much easier and less prone to error.
It shoudl ALWAYS be preferred for a driver that does not need to run on
down-rev platforms.

In this specific case, using AllocateAdapterChannel/IoMapTransfer would be a
particularly bad idea because it does not support chained MDLs. Assuming he
even NEEDS this feature, of course.

Peter
OSR