I have diagnostic setup that sends arbitrary CDBs, at arbitrary queue
depths, to arbitrary SCSI devices. In order to get around the SPTI
limitations, I have a SCSI bus filter that changes the PnP IDs from whatever
the Port driver makes them into something only my custom class driver
recognizes. I have a usermode app that sends IOCTLs to the class driver,
which validates some things and sends it along. I don’t really want to
define a buch of IOCTLs for the different CDBs, so I’m just using one for
all of them.
If I define the IOCTL as METHOD_BUFFERED, everything works OK, though the
memcopy can be obnoxious if there are a lot of READs or WRITEs with large
transfer sizes, so I’d like to do a DIRECT. However, that would mean at
least three IOCTLs, and probably more, so I’m trying to figure out if it’s
possible to use METHOD_NEITHER.
So far, I can see how to map the user-buffer into kernel space with the
following sequence (minus lots of error checking) in my Dispatch routine,
which I’m sure is called in the User context due to being, as far as the App
is concerned, at the same level as the FS in the stack:
__try
{
ProbeForRead on the Type3InBuffer
Copy the buffer (which looks a lot like SCSI_PASS_THROUGH) to safe
storage
Allocate an SRB
IoAllocateMdl on Irp->UserBuffer with length from data in safe storage
MmProbeAndLockPages(mdl, UserMode, IoModifyAccess);
get a system VA from MmGetSystemAddressForMdlSafe
put that address into SRB->DataBuffer
put MDL into Irp->MdlAddress
put that SRB into NextIoStack->Param.Scsi.Srb
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
GetExceptionCode()
blah, blah, blah…
}
What I don’t know is how to get back into the User context I started in, so
I can unmap & unlock the user buffer and free the MDL. I’m pretty sure I
can count on completion routines being called in “arbitrary” contexts, and I
think unmapping/unlocking anywhere except the user context will kill the
system in very short order. Are these beliefs correct?
I searched the XP & 2K Fastfat source from the XPSP1 IFS Kit for
METHOD_NEITHER. They don’t even try to manage this asynchronously, per the
comment below, which is why I am thinking that attempting this is rather a
Quixotic endeavor.
//
// Some of these Fs Controls use METHOD_NEITHER buffering. If the previous
mode
// of the caller was userspace and this is a METHOD_NEITHER, we have the
choice
// of realy buffering the request through so we can possibly post, or making
the
// request synchronous. Since the former was not done by design, do the
latter.
//
Anyone have a lifeline to throw me, or do I need to:
a) do multiple IOCTLs
b) live with some big memcopies
Thanks,
Phil
Philip D. Barila
Seagate Technology, LLC
(720) 684-1842
As if I need to say it: Not speaking for Seagate.
E-mail address is pointed at a domain squatter. Use reply-to instead.