>The sequence is:
@InCallerContext
This all looks OK to me.
@InDeviceIoControl
- get the pinned pointer memory object from the context object associated
with the Request
- get the buffer from the memory object
QUESTION - can I get the Mdl directly from the memory object so i don’t
have to allocate the mdl?
I don’t see an API that will easily grab this for you, maybe there’s some
way you can though an someone else will chime in.
- IoAllocateMdl on the buffer.
– I should not have to do this, but it only works this way…
– Probeandlockpages over the Mdl
Aha! That’s it! Yes, you absolutely have to do something other than just
allocate the MDL structure. When you create an MDL, you do two steps:
-
Allocate enough space for the MDL structure. The MDL structure is
variable length, a fixed portion at the beginning and a variable length tail
that has one entry per-page of memory that the allocation consumes. All
IoAllocateMdl does is allocate enough space for the structure and initialize
the fixed portion.
-
Populate the variable length tail with the actual physical pages of the
allocation. This is what MmProbeAndLockPages does.
Without doing step #2, you’re doing DMA to whatever pages the garbage at the
end of the MDL structure point to. I’m surprised you haven’t experienced a
fiery death yet.
As an optimization here, you could actually call MmBuildMdlForNonPagedPool
instead of MmProbeAndLockPages. Sounds strange, yes, but the API is poorly
named. It should really be, “MmBuildMdlForNonPageableMemory”. You’re
basically saying that the memory is already guaranteed to be resident for
the lifetime of the MDL and that it doesn’t need to be probed for access, so
the memory manager can shortcut a lot of processing and just fill in the
tail of the MDL with the physical page numbers.
That should fix your current design. However, I still think that you have
created an extra step by being good and using the KMDF APIs.
The easiest thing to do is to build your MDL as part of your in caller
context callback. So, extract the pointer from the system buffer and do:
IoAllocateMdl()
MmProbeAndLockPages()
MmGetSystemAddressForMdlSafe() - this is optional, only if you need a kernel
virtual address to the buffer
Then stuff the MDL someplace. Then in InDeviceIoControl, pass the MDL to
your hardware. When you’re done, MmUnlockPages and IoFreeMdl.
This is essentially what WdfProbe is doing for you, so you’re just
duplicating the work.
-scott
–
Scott Noone
Consulting Associate and Chief System Problem Analyst
OSR Open Systems Resources, Inc.
http://www.osronline.com
wrote in message news:xxxxx@ntdev…
well said… way more complex than I would have liked it to be.
This is my second venture into KMDF and I am expecting that there is
something happening for me that I am not taking advantage of- - or simply
missed something.
The Mdl is getting build from a pointer derived from the InCallerContext
pinned memory object representing the user buffer reference. The sequence
is:
@InCallerContext
- get my IOCTL structure that has the user pointer embedded within using
WdfRequestRetrieveInputBuffer
- pin my user buffer from the reference (bufffer will be used as a READ)
using WdfRequestProbeAndLockUserBufferForWrite. (base structure passed is
good data)
- put the returned Memory obect that references the bufferpointer into a
created context that is attached to the Request. (just like they say i
should in the docs)(And that should do the business)
@InDeviceIoControl
- get the pinned pointer memory object from the context object associated
with the Request
- get the buffer from the memory object
QUESTION - can I get the Mdl directly from the memory object so i don’t have
to allocate the mdl?
- IoAllocateMdl on the buffer.
– I should not have to do this, but it only works this way…
– Probeandlockpages over the Mdl
- pass the Mdl along to the firewire stack (synchronous call to ASYNC_READ)
– I should not have to do this, but it only works this way…
– MmFreePages
If I don’t do the extra probe and lock and free, the memory is not correct
coming back from the hardware. If I use the more simple “IoEvtRead” path
where the user buffer is already pinned and set, then it simply works – no
extra pinnings.
If I Call a “get unsafe user buffer mdl” call, I can see the data in kernel
space, but the buffer is not coherent in user space.
My IOCTL is “buffered”, but my understanding is that this only means the
structure I am passing. The “right way” to do this – i think – is to have
the data block below the structure so that it can get pulled in along with
the structure I am passing down to the IOCTL.
typedef struct _goo { int foo; int bar; char data[1]; } goo;
The ASYNC_WRITE path works without issue using the “InCallerContext” probe
and lock of the “read” buffer.
Thanks!