The IOCTL is METHOD_BUFFERED, but contains an embedded pointer to the
data buffer. It is the responsibility of the port driver to validate
and lock down the buffer pointed to here. The storage stack ensures
that IOCTLs are processed in the original context they were sent in (if
sent at PASSIVE_LEVEL), so there is a guarantee that the correct context
is used. This design allows the parameters to be locked down and
double-buffered by the IO manager without incurring the performance
penalty of double-buffering the data transfer buffer.
You can test test if the adapter is reporting a broken alignment
requirement directly as follows:
The reality of the matter is that all adapters can have a maximum
alignment requirement of MEMORY_ALLOCATION_ALIGNMENT (wdm.h, ntdef.h).
This is because many allocations done in kernel mode presume the
appropriate alignment is obtained from calls to ExAllocatePool() today.
While larger alignment requirements are theoretically possible, and
should be coded to in any production code (for future OS compatibility),
you can easily DECLSPEC_ALIGN a local variable to any alignment you
require for quick testing purposes. For the below test, you can force a
memory alignment as follows:
TRACK_INFORMATION2 DECLSPEC_ALIGN(MEMORY_ALLOCATION_ALIGNMENT)
trackInformation;
This will force the compiler (at least the MSFT one) to enforce this
alignment requirement for the local variable. If you allocation size is
large, or you want a variable alignment requirement (as is required in
SPT_DIRECT) another way to ensure you get an aligned buffer is as
follows:
- Get the alignment mask from the adapter. This is always (alignment
size - 1).
- BYTE * p = Allocate memory of size (requiredSize + alignment mask).
Memory allocation must be byte pointer (pointer math is always fun).
- Have a second pointer which is used to store the resulting data, BYTE
* pAligned.
- pAligned = (p + alignment mask) & (~alignment mask) – this gives you
the aligned buffer.
This is somewhat messy, but if you write a wrapper function for
allocating and freeing aligned buffers, it can be very useful. If you
test with MEMORY_ALLOCATION_ALIGNMENT, this should easily allow you to
test whether the IOCTL is failing due to the alignment of the buffer you
are sending to the device.
I hope that helps.
.
P.S. - I’d be interested in knowing which port driver(s) you are seeing
this behavior on. Perhaps the vendor doesn’t realize they have this
problem.
-----Original Message-----
From: Chuck Batson [mailto:xxxxx@cbatson.com]
Sent: Tuesday, October 28, 2003 8:41 AM
Subject: RE: Memory contiguity in user mode
The definition for IOCTL_SCSI_PASS_THROUGH_DIRECT indicates
METHOD_BUFFERED, although the docs say:
“To bypass buffering in system memory, callers should use
IOCTL_SCSI_PASS_THROUGH_DIRECT. When handling an
IOCTL_SCSI_PASS_THROUGH_DIRECT request, the system locks down the buffer
in user memory and the device accesses this memory directly.”
Despite that the IOCTL is METHOD_BUFFERED, it would seem (if I’m reading
the docs right) that no intermediate system memory buffer is used, the
user buffer is locked down, and the resulting MDL is sent to the driver.
I’m beginning to agree with your assessment of the driver. Silly me, I
wanted to blame my own code before the driver’s. =^)
Chuck
----- Original Message -----
From: “Arlie Davis”
To: “Windows System Software Devs Interest List”
Sent: Tuesday, October 28, 2003 8:54 PM
Subject: [ntdev] RE: Memory contiguity in user mode
> Well, you’ve proven that allocating an N*64K, 64K-aligned chunk works
> around the problem. But you haven’t yet proven that the problem is
> contiguity. More likely, the driver is simply broken, and it lies
about
> its alignment requirements.
>
> I would believe that the driver is broken before I would believe that
> the driver required the physical pages to be contiguous.
> NtDeviceIoControl locks down the pages at the beginning of the call,
> before even handing the request to device driver. (That is, if the
I/O
> control is marked for this behavior – check the transfer encoding
bits
> of the I/O control code, and check to see whether it is buffered,
> direct, or neither.) If a driver fails to correctly handle an MDL
> (which describes the locked-down list of pages), then the driver is
> thoroughly broken. Come to think of it, the broken alignment thing is
> bogus, too, but slightly less bogus.
>
> – arlie
>
>
> -----Original Message-----
> From: xxxxx@lists.osr.com
> [mailto:xxxxx@lists.osr.com] On Behalf Of Chuck Batson
> Sent: Tuesday, October 28, 2003 12:57 AM
> To: Windows System Software Devs Interest List
> Subject: [ntdev] RE: Memory contiguity in user mode
>
>
> Thank you for your reply, Arlie.
>
> This is entirely true, although I thought it might be possible that
> sometimes the OS was using actual page sizes larger than the system
page
> granularity. In which case the contiguity would be maintained barring
> the OS deciding to split up a large page into smaller ones.
>
> I’m using an IOCTL_SCSI_PASS_THROUGH_DIRECT in user mode, and on a
> certain device (other devices have exhibited no problems) this will
fail
> with ERROR_INVALID_PARAMETER depending on the return data buffer
pointer
> I supply in the SRB (SCSI_PASS_THROUGH_DIRECT.DataBuffer, not the
buffer
> supplied to DeviceIoControl()). At first I thought the device might
> require certain alignment restrictions, but I queried the device’s bus
> adapter which had an AlignmentMask (from STORAGE_ADAPTER_DESCRIPTOR)
of
> 0, which the documentation indicates as meaning byte alignment is
> sufficient. However, if I allocate a 64KB virtual memory block
aligned
> to a 64KB boundary, the DeviceIoControl() succeeds. I was thus led to
> conclude that physical contiguity, rather than alignment, was the
> culprit (unless the adapter’s driver is lying to me!). This was a bit
> puzzling, since if the page granularity is really 4KB on x86, then my
> 64KB buffer really has no guarantee of any physical contiguity.
>
> If I can query the physical contiguity, this will tell me what’s going
> on. If I have a phsyically non-contiguous but aligned buffer, and
> DeviceIoControl() fails, then I know contiguity is the issue. If I
have
> a physically contiguous but non-aligned buffer, and DeviceIoControl()
> fails, then I know the driver is lying about alignment restrictions.
>
> Thanks,
>
> Chuck
>
> ----- Original Message -----
> From: “Arlie Davis”
> To: “Windows System Software Devs Interest List”
> Sent: Tuesday, October 28, 2003 12:16 PM
> Subject: [ntdev] RE: Memory contiguity in user mode
>
>
> > It’s useless to determine the mapping from virtual addresses to
> physical
> > addresses, at least in user-mode. Reason being, that the mapping
can
> > potentially change after each tiny assembly instruction. So, even
if
> > there were a system call to query the mapping, by the time you get
the
>
> > information, it’s useless.
> >
> > Can you give information on why you want to do this? There may be a
> > different way to solve your problem.
> >
> > – arlie
> >
> >
> > -----Original Message-----
> > From: xxxxx@lists.osr.com
> > [mailto:xxxxx@lists.osr.com] On Behalf Of Chuck Batson
> > Sent: Monday, October 27, 2003 11:54 PM
> > To: Windows System Software Devs Interest List
> > Subject: [ntdev] Memory contiguity in user mode
> >
> >
> > In user mode, is it possible to determine the physical memory
address
> > from a virtual address? Or might there be some other way to
determine
>
> > the physical contiguity of a given virtual memory range? Note, I
just
>
> > want to query the physical contiguity. I don’t see any way to do
> these
> > things in user mode, but perhaps someone knows a way.
> >
> > Thank you,
> >
> > Chuck
> >
> >
> > —
> > Questions? First check the Kernel Driver FAQ at
> > http://www.osronline.com/article.cfm?id=256
> >
> > You are currently subscribed to ntdev as: xxxxx@sublinear.org To
> > unsubscribe send a blank email to xxxxx@lists.osr.com
> >
> >
> > —
> > Questions? First check the Kernel Driver FAQ at
> http://www.osronline.com/article.cfm?id=256
> >
> > You are currently subscribed to ntdev as: xxxxx@cbatson.com To
> > unsubscribe send a blank email to xxxxx@lists.osr.com
> >
>
>
> —
> Questions? First check the Kernel Driver FAQ at
> http://www.osronline.com/article.cfm?id=256
>
> You are currently subscribed to ntdev as: xxxxx@sublinear.org To
> unsubscribe send a blank email to xxxxx@lists.osr.com
>
>
> —
> Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256
>
> You are currently subscribed to ntdev as: xxxxx@cbatson.com
> To unsubscribe send a blank email to xxxxx@lists.osr.com
>