Confusing return from StorPortGetSystemAddress

I’m trying to use StorPortGetSystemAddress to get a VA I can use to meet the alignment and transfer length requirements for my device. My Storport miniport is setting MapBuffers to STOR_MAP_NON_READ_WRITE_BUFFERS in the HW_INITIALIZATION_DATA.

I thought I would be able to use StorPortGetSystemAddress to retrieve a VA for both Read/Write and non-Read/Write requests. However, the VA I’m getting from StorPortGetSystemAddress has me confused. I expected to either get back the same VA contained in DataBuffer, or to get back a different VA which pointed to the same physical memory.

Example:
StorPortGetSystemAddress returns 0xfffffa8007564560 Srb-\>Databuffer is 0xfffffa6006ec5560
SCATTER_GATHER_ELEMENT.PhysicalAddress 0xb30d5560

!pte 0xfffffa80`07564560 (StorPortGetPhysicalAddress)
VA fffffa8007564560
PXE @ FFFFF6FB7DBEDFA8 PPE at FFFFF6FB7DBF5000 PDE at FFFFF6FB7EA001D0 PTE at FFFFF6FD4003AB20
contains 0000000105600863 contains 0000000105601863 contains 00000001DE6009E3 contains 0000000000000000
pfn 105600 —DA–KWEV pfn 105601 —DA–KWEV pfn 1de600 -GLDA–KWEV LARGE PAGE pfn 1de764

!pte 0xfffffa60`06ec5560 (DataBuffer)
VA fffffa6006ec5560
PXE @ FFFFF6FB7DBEDFA0 PPE at FFFFF6FB7DBF4C00 PDE at FFFFF6FB7E9801B8 PTE at FFFFF6FD30037628
contains 0000000105784863 contains 0000000105783863 contains 00000000B335C863 contains 00000000B30D5963
pfn 105784 —DA–KWEV pfn 105783 —DA–KWEV pfn b335c —DA–KWEV pfn b30d5 -G-DA–KWEV

What exactly is StorPortGetPhysicalAddresses VA pointing to? Can I not use this API if the memory is already mapped?

STOR_MAP_NON_READ_WRITE_BUFFERS means that only Non Read/Write Buffers are
mapped and thus only those SRBs have valid Databuffer fields. Perhaps you
meant to use STOR_MAP_ALL_BUFFERS?

Mark Roddy

On Wed, Aug 10, 2011 at 5:47 PM, wrote:

> STOR_MAP_NON_READ_WRITE_BUFFERS
>

Mark,

The documentation (from 7600.16385.1) states that STOR_MAP_ALL_BUFFERS is not implemented, so I assumed I would have to use StorPortGetSystemAddress to access the buffers of read/write requests.

Instead of having two different code paths for read/write vs non-read/write requests, I implemented my code to just always use the pointer I received from StorPortGetSystemAddress. I just ran a test with STOR_MAP_NO_BUFFERS set, and I’m still finding that the VA I’m getting from the API does not point to the memory in the SGL.

If I take the physical address in the first s/g entry, and type
!eb 1 2 3 4
And then db srb->DataBuffer, I see something like
1 2 3 4 0 0 0 0 0
But If I dump the VA given to me by StorPortGetSystemAddress, then I’ll get all 0’s. This agrees with the !pte output telling me that the two VA’s are pointing at different memory. I just can’t figure out what StorPortGetSystemAddress is pointing at, and how I would get a VA that points to the SRB’s MDL if it’s not already in Srb->DataBuffer.

Jeff

srb->DataBuffer may or may not be useable to access the buffer. If the buffer is not mapped, DataBuffer is the same as MDL’s original virtual address, which could even be zero.

The return from StorPortGetSystemAddress CAN be used for the buffer access.

I guess based on the replies I’m getting that StorPortGetSystemAddress is supposed to return a VA that points to the same physical memory as the MDL. So maybe I’m not using the function correctly. I’ll check again. To be clear…

If I edit the physical memory in the first entry of the Windows supplied scatter/gather list (using !eb), I see the change (using db) reflected in the memory pointed to srb->DataBuffer when it’s mapped, and I see the change (using !db -m) reflected at the physical memory address. However, I do not see a change (again using db) at the memory pointed to by the pointerI get back from StorPortGetSystemAddress.

If I do the opposite and edit the memory using eb at the pointer returned by StorPortGetSystemAddress and look for the change at the physical address with !db -m, then I do not see the change I made.

Also, the !pte results seem to confirm that the virtual addresses are pointing to different physical memory regions.

If you got a SGL, it may point to a bounce buffer. You can either access the buffer directly, or use DMA, but not both at the same time.

So just to put a bow on this thread…

The documentation for StorPortGetSystemAddress states “The StorPortGetSystemAddress routine returns a virtual address in system space for the data buffer of the specified SCSI request block (SRB).”

What it actually returns is a virtual address for the user space buffer that was passed into the O/S.

If the user used IOCTL_SCSI_PASS_THROUGH, then this will not be the same buffer that is pointed to by the scatter/gather list returned by StorPortGetScatterGatherList because of bounce buffering. It is, I believe, the buffer pointed to by StorPortGetOriginalMdl().

If the user used IOCTL_SCSI_PASS_THROUGH_DIRECT, then the VA *does* point to the SGL because no bounce buffering is being done.

There doesn’t appear to a way (at least with the Storport framework) to get a virtual address for a the scatter/gather list returned by StorPortGetScatterGatherList if the CDB is read or write command when the request is being bounced.