Completing METHOD_NEITHER

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.

Do Kernel APCs solve your problem?

-Srin.

-----Original Message-----
From: Phil Barila [mailto:xxxxx@Seagate.com]
Sent: Monday, March 03, 2003 2:22 PM
To: NT Developers Interest List
Subject: [ntdev] Completing METHOD_NEITHER

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.


You are currently subscribed to ntdev as: xxxxx@nai.com
To unsubscribe send a blank email to xxxxx@lists.osr.com

Color me stuipid, but what 3 IOCTLs? I can see Read and Write but what is
numero treo? Besides, you may have to define 3 IOTCLs but in most cases all
of the processing is common so your switch would probably be

case IOCTL_READ:
case IOCTL_WRITE:
case IOCTL_WHATEVER:
do something
do a transfer (buffer pointer, ((read) ? Read : (hellIfIKnow) ? whatever
: Write))
do some more
break;

Or am I being to simple minded?


Gary G. Little
Have Computer, Will Travel …
909-698-3191
909-551-2105

“Phil Barila” wrote in message
news:xxxxx@ntdev…
>
> 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.
>
>
>
>

“Gary G. Little” wrote in message
news:xxxxx@ntdev…
>
> Color me stuipid, but what 3 IOCTLs? I can see Read and Write but what is
> numero treo? Besides, you may have to define 3 IOTCLs but in most cases
all
> of the processing is common so your switch would probably be
>
> case IOCTL_READ:
> case IOCTL_WRITE:
> case IOCTL_WHATEVER:
> do something
> do a transfer (buffer pointer, ((read) ? Read : (hellIfIKnow) ?
whatever
> : Write))
> do some more
> break;
>
> Or am I being to simple minded?
>
> –
> Gary G. Little
> Have Computer, Will Travel …
> 909-698-3191
> 909-551-2105
>
> “Phil Barila” wrote in message
> news:xxxxx@ntdev…
> >
> > 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.
> >
> >
> >
> >
>
>
>
>

Another thought —

Use METHOD_NEITHER, but lock it down before you leave PASSIVE_LEVEL. Why can
you not simply create an MDL for the buffer?


Gary G. Little
Have Computer, Will Travel …
909-698-3191
909-551-2105

“Gary G. Little” wrote in message
news:xxxxx@ntdev…
>
> Color me stuipid, but what 3 IOCTLs? I can see Read and Write but what is
> numero treo? Besides, you may have to define 3 IOTCLs but in most cases
all
> of the processing is common so your switch would probably be
>
> case IOCTL_READ:
> case IOCTL_WRITE:
> case IOCTL_WHATEVER:
> do something
> do a transfer (buffer pointer, ((read) ? Read : (hellIfIKnow) ?
whatever
> : Write))
> do some more
> break;
>
> Or am I being to simple minded?
>
> –
> Gary G. Little
> Have Computer, Will Travel …
> 909-698-3191
> 909-551-2105
>
> “Phil Barila” wrote in message
> news:xxxxx@ntdev…
> >
> > 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.
> >
> >
> >
> >
>
>
>
>

To start off … there’s nothing about a METHOD_BUFFERED IOCTL that says
you can’t play the same tricks with data buffers.

So if your thing that looks a lot like SPT was something like:

PVOID DataBuffer;
ULONG DataBufferLength;
PVOID SenseBuffer;
ULONG SenseBufferLength;
UCHAR Cdb[16];

You could receive this from a METHOD_BUFFERED IOCTL in Irp->SystemBuffer
already in safe storage. You can still use IoAllocateMdl to build MDLs
for the data & sense buffers. You don’t need to map the data buffer
into system VA space (scsiport will do this automatically if the
miniport requests it … Doing it yourself could hide bugs where the
miniport attempts to use the data buffer without setting MapBuffers)
just use the result of MmGetMdlVirtualAddress. The sense buffer you’d
need to map into system VA space and provide the pointer in the SRB.

But that said …

Once a buffer is locked the MDL contains a pointer to the process which
locked the pages (which is the process that owns the pages by
definition). I believe you can unlock them in any context. You can
unmap them from system VA space in any process since that VA space is
shared.

-p

Ps: it’s still not clear to me (or I’ve forgotten) why you can’t simply
reassign the service on the device you want to test from disk.sys to
philsmagicdriver.sys which would have this IOCTL support in it instead
of making a bus filter which mucks with PNP ids. But that has little to
do with any of the above.

-----Original Message-----
From: Phil Barila [mailto:xxxxx@Seagate.com]
Sent: Monday, March 03, 2003 2:22 PM
To: NT Developers Interest List

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.


You are currently subscribed to ntdev as: xxxxx@microsoft.com To
unsubscribe send a blank email to xxxxx@lists.osr.com

Peter,

Thanks for the response.

To explain why the filter, there’s no other way I know of to cleanly make a
disk look like something else. I have another project that will follow this
diagnostic thing in which I need to make a disk look like something else,
which just happens to have a windows class driver, so I won’t be replacing
that layer. Hence, I need a filter that will intercept the Irps from the
class driver for the device I’m emulating, and turn them into Irps for a
disk. So first, I need to change the PnP IDs to something the system
recognizes as an instance of the device I need to emulate. In both cases,
the only place I see to do this properly is a SCSI bus upper filter. Yes,
it’s nuts, but I have to do it. And I’m intentionally not revealing what
the emulated device is.

Back to my DiagClas driver, for METHOD_BUFFERED, I did it the easy way and
used offsets, so my structure, sense and data buffers are in a contiguous
blob, and nothing needed except to get an MDL. Since IO manager locked the
buffer, IO manager unlocks it. However, when moving large amounts of data,
there is a big overhead because of the copy. I may be trying to dump a lot
of oddball CDBs on the port, but that doesn’t mean I’m not doing a lot of
READ10s, too.

If I understand you right, I can still use METHOD_BUFFERED, but don’t append
the buffer to the input struct, just put a pointer in the struct, instead of
the offset. I can still append the Sense buffer, since that’s pretty small.
If I do that, I need to get a VA for the sense buffer and put that into the
SRBin my Dispatch routine. Additionally, I lock the buffer down, but don’t
map it, since the port driver is supposed to handle that. But I do need to
get a VA (but not a system VA) for the MDL, and put that into the SRB, is
this right?

If I give the port driver a Sense buffer, will it always use it, or will it
allocate it’s own? If I don’t give it a Sense buffer, will it always
auto-sense and PORT_ALLOCATE the sense buffer?

Lastly, in my Completion routine, I Unlock the buffer. Do I need to unmap
it, or does the system do that?

Phil

Philip D. Barila
Seagate Technology, LLC
(720) 684-1842
As if I need to say it: Not speaking for Seagate.

“Peter Wieland” wrote in message
news:xxxxx@ntdev…

To start off … there’s nothing about a METHOD_BUFFERED IOCTL that says
you can’t play the same tricks with data buffers.

So if your thing that looks a lot like SPT was something like:

PVOID DataBuffer;
ULONG DataBufferLength;
PVOID SenseBuffer;
ULONG SenseBufferLength;
UCHAR Cdb[16];

You could receive this from a METHOD_BUFFERED IOCTL in Irp->SystemBuffer
already in safe storage. You can still use IoAllocateMdl to build MDLs
for the data & sense buffers. You don’t need to map the data buffer
into system VA space (scsiport will do this automatically if the
miniport requests it … Doing it yourself could hide bugs where the
miniport attempts to use the data buffer without setting MapBuffers)
just use the result of MmGetMdlVirtualAddress. The sense buffer you’d
need to map into system VA space and provide the pointer in the SRB.

But that said …

Once a buffer is locked the MDL contains a pointer to the process which
locked the pages (which is the process that owns the pages by
definition). I believe you can unlock them in any context. You can
unmap them from system VA space in any process since that VA space is
shared.

-p

Ps: it’s still not clear to me (or I’ve forgotten) why you can’t simply
reassign the service on the device you want to test from disk.sys to
philsmagicdriver.sys which would have this IOCTL support in it instead
of making a bus filter which mucks with PNP ids. But that has little to
do with any of the above.

Gary,

Thanks for the questions and suggestions.

Responding to both messages below…

Why 3, at least?
For those CDB OpCodes that I know data is coming out of the device,
METHOD_OUT_DIRECT. For those that I know move data into the device,
METHOD_IN_DIRECT. For everything else, METHOD_BUFFERED. I’m sure not going
to use METHOD_NEITHER for this, if I’ve gone to the pain of setting up
independent code paths for the stuff I know is going to cause the biggest
data movement.

Lock it down before I leave passive level:
That’s what I was describing, though Peter W has kindly pointed out that
while I need to stuff the VA into the SRB, I don’t need a system VA, as the
port is responsible for that, if I understood Peter correctly. So I could
cut some of what I wrote away. Again, if I understood correctly, Peter also
pointed out that I could still use METHOD_BUFFERED on the input struct, and
then not have to copy it, just extract the pointer to the user buffer and
lock that down, so I could cut some more of it away.

More importantly, if I understood right, Peter says I can unlock the pages
in an arbitrary context, so the completion routine can do that safely.
Where I got confused is that Unmapping pages mapped for UserMode in an
arbitrary context will unmap the wrong stuff. Unmapping pages mapped for
KernelMode is safe in any context, if I now understand the
MmUnMapLockedPages docs. Since MmGetSystemAddressForMdlSafe maps for
KernelMode, I think I would be safe, if I needed to map it. Since Peter
says I don’t, it appears that I don’t have any issue here.

Thanks,

Phil

Philip D. Barila
Seagate Technology, LLC
(720) 684-1842
As if I need to say it: Not speaking for Seagate.

“Gary G. Little” wrote in message
news:xxxxx@ntdev…
>
> Another thought —
>
> Use METHOD_NEITHER, but lock it down before you leave PASSIVE_LEVEL. Why
can
> you not simply create an MDL for the buffer?
>
> –
> Gary G. Little
> Have Computer, Will Travel …
> 909-698-3191
> 909-551-2105
>
> “Gary G. Little” wrote in message
> news:xxxxx@ntdev…
> >
> > Color me stuipid, but what 3 IOCTLs? I can see Read and Write but what
is
> > numero treo? Besides, you may have to define 3 IOTCLs but in most cases
> all
> > of the processing is common so your switch would probably be
> >
> > case IOCTL_READ:
> > case IOCTL_WRITE:
> > case IOCTL_WHATEVER:
> > do something
> > do a transfer (buffer pointer, ((read) ? Read : (hellIfIKnow) ?
> whatever
> > : Write))
> > do some more
> > break;
> >
> > Or am I being to simple minded?
> >
> > –
> > Gary G. Little
> > Have Computer, Will Travel …
> > 909-698-3191
> > 909-551-2105

  1. my suggestion is to use the SetupDI API to change the service on the
    devices you want your class driver running on to be your service. You
    could even put in a disk co-installer which would do this automatically
    whenever it saw an appropriate disk. I suspect I’m happier not knowing
    what you’re emulating :slight_smile:

  2. just like IOCTL_SCSI_PASS_THROUGH - small buffers work great but
    large ones really really suck.

  3. you’ve understood correctly. Just think of METHOD_BUFFERED as
    METHOD_NEITHER where the IO system takes care of that first and last
    copy for you (from input and to output buffers) automatically. You can
    still access the process address space (assuming no driver above you has
    posted to a different thread).

And the DataBuffer you provide can be any arbitrary address - it’s used
along with the virtual address in the MDL to determine buffer offset by
the port driver. The port driver will acquire a valid system VA if
needed for the miniport.

  1. Not sure offhand on this one. Sorry.

  2. I think unmapping occurs as part of unlocking, but if you wanted to
    be safe you can unmap first.

-p

-----Original Message-----
From: Phil Barila [mailto:xxxxx@Seagate.com]
Sent: Tuesday, March 04, 2003 8:47 AM
To: NT Developers Interest List

Peter,

Thanks for the response.

To explain why the filter, there’s no other way I know of to cleanly
make a
disk look like something else. I have another project that will follow
this
diagnostic thing in which I need to make a disk look like something
else,
which just happens to have a windows class driver, so I won’t be
replacing
that layer. Hence, I need a filter that will intercept the Irps from
the
class driver for the device I’m emulating, and turn them into Irps for a
disk. So first, I need to change the PnP IDs to something the system
recognizes as an instance of the device I need to emulate. In both
cases,
the only place I see to do this properly is a SCSI bus upper filter.
Yes,
it’s nuts, but I have to do it. And I’m intentionally not revealing
what
the emulated device is.

Back to my DiagClas driver, for METHOD_BUFFERED, I did it the easy way
and
used offsets, so my structure, sense and data buffers are in a
contiguous
blob, and nothing needed except to get an MDL. Since IO manager locked
the
buffer, IO manager unlocks it. However, when moving large amounts of
data,
there is a big overhead because of the copy. I may be trying to dump a
lot
of oddball CDBs on the port, but that doesn’t mean I’m not doing a lot
of
READ10s, too.

If I understand you right, I can still use METHOD_BUFFERED, but don’t
append
the buffer to the input struct, just put a pointer in the struct,
instead of
the offset. I can still append the Sense buffer, since that’s pretty
small.
If I do that, I need to get a VA for the sense buffer and put that into
the
SRBin my Dispatch routine. Additionally, I lock the buffer down, but
don’t
map it, since the port driver is supposed to handle that. But I do need
to
get a VA (but not a system VA) for the MDL, and put that into the SRB,
is
this right?

If I give the port driver a Sense buffer, will it always use it, or will
it
allocate it’s own? If I don’t give it a Sense buffer, will it always
auto-sense and PORT_ALLOCATE the sense buffer?

Lastly, in my Completion routine, I Unlock the buffer. Do I need to
unmap
it, or does the system do that?

Phil

Philip D. Barila
Seagate Technology, LLC
(720) 684-1842
As if I need to say it: Not speaking for Seagate.

“Peter Wieland” wrote in message
news:xxxxx@ntdev…

To start off … there’s nothing about a METHOD_BUFFERED IOCTL that says
you can’t play the same tricks with data buffers.

So if your thing that looks a lot like SPT was something like:

PVOID DataBuffer;
ULONG DataBufferLength;
PVOID SenseBuffer;
ULONG SenseBufferLength;
UCHAR Cdb[16];

You could receive this from a METHOD_BUFFERED IOCTL in Irp->SystemBuffer
already in safe storage. You can still use IoAllocateMdl to build MDLs
for the data & sense buffers. You don’t need to map the data buffer
into system VA space (scsiport will do this automatically if the
miniport requests it … Doing it yourself could hide bugs where the
miniport attempts to use the data buffer without setting MapBuffers)
just use the result of MmGetMdlVirtualAddress. The sense buffer you’d
need to map into system VA space and provide the pointer in the SRB.

But that said …

Once a buffer is locked the MDL contains a pointer to the process which
locked the pages (which is the process that owns the pages by
definition). I believe you can unlock them in any context. You can
unmap them from system VA space in any process since that VA space is
shared.

-p

Ps: it’s still not clear to me (or I’ve forgotten) why you can’t simply
reassign the service on the device you want to test from disk.sys to
philsmagicdriver.sys which would have this IOCTL support in it instead
of making a bus filter which mucks with PNP ids. But that has little to
do with any of the above.


You are currently subscribed to ntdev as: xxxxx@microsoft.com
To unsubscribe send a blank email to xxxxx@lists.osr.com

.

Back at you.

  1. I still need a translation layer, in order to map the CDBs from the
    emulated device to the disk, so I don’t see the advantage of forcing the
    class driver for my emulated device to load as the function driver for my
    particular disk device. Are you saying that I could make a simpler lower
    class filter if I did this?

  2. Thanks for the confirmation.

  3. Glad I’m beginning to show some vestigial signs that I might be able to
    see a clue. :slight_smile:

  4. I guess I’ll find out over time.

  5. I’ll find this one out quick enough, if it needs to be unmapped before
    unlocking. Since I don’t explicitly map, I’ll leave it alone unless I find
    out that I need to unmap to avoid a bugcheck.

Thanks again,

Phil

Philip D. Barila
Seagate Technology, LLC
(720) 684-1842
As if I need to say it: Not speaking for Seagate.

“Peter Wieland” wrote in message
news:xxxxx@ntdev…

1) my suggestion is to use the SetupDI API to change the service on the
devices you want your class driver running on to be your service. You
could even put in a disk co-installer which would do this automatically
whenever it saw an appropriate disk. I suspect I’m happier not knowing
what you’re emulating :slight_smile:

2) just like IOCTL_SCSI_PASS_THROUGH - small buffers work great but
large ones really really suck.

3) you’ve understood correctly. Just think of METHOD_BUFFERED as
METHOD_NEITHER where the IO system takes care of that first and last
copy for you (from input and to output buffers) automatically. You can
still access the process address space (assuming no driver above you has
posted to a different thread).

And the DataBuffer you provide can be any arbitrary address - it’s used
along with the virtual address in the MDL to determine buffer offset by
the port driver. The port driver will acquire a valid system VA if
needed for the miniport.

4) Not sure offhand on this one. Sorry.

5) I think unmapping occurs as part of unlocking, but if you wanted to
be safe you can unmap first.

-p