ScsiPortGetPhysicalAddress

SCSI_PHYSICAL_ADDRESS ScsiPortGetPhysicalAddress(HwDeviceExtension, Srb,
    VirtualAddress, Length)
IN PVOID  HwDeviceExtension;
IN PSCSI_REQUEST_BLOCK  Srb;    /* optional    */
IN PVOID  VirtualAddress;
OUT ULONG  *Length;
 

Translates a virtual address range to a physical address range for a DMA operation.

HwDeviceExtension
Points to the miniport driver's storage for per-adapter data.
Srb
Points to a SCSI request block, if the VirtualAddress to be translated comes from an SRB's DataBuffer field; otherwise, this pointer is NULL.
VirtualAddress
Specifies the virtual address to be translated. The Srb pointer is required if the address came from the DataBuffer field of an SRB.
Length

See below.

An Srb parameter is not required if the VirtualAddress is in an UncachedExtension, SenseInfoBuffer or the SrbExtension. If an Srb is provided, the VirtualAddress must be within the range of DataBuffer or must be the pointer from SenseInfoBuffer field specified by the Srb. This function can be called to translate an extension address only if NeedPhysicalAddresses was specified in the HW_INITIALIZATION_DATA structure.

ScsiPortGetPhysicalAddress can be used to build a scatter/gather list for data transfers that span pages. Note that the Length returned can be greater than the length of the DataBuffer specified in the Srb parameter.

The general function performed by ScsiPortGetPhysicalAddress follows:

  1. 1. If (Srb != NULL) && (VirtualAddress lies within the Srb's DataBuffer) scan the corresponding IOP's IOR_sgd_lin_phys field to obtain the desired SG element and physical offset within that element. The returned length is the number of bytes from the offset within the SG element, to the end of the SG element.

    (else)

  2. 2. If (VirtualAddress lies within the IOP Memory Pool)

    The physical address is obtained by finding the offset within the memory pool and adding IDA_ios_mem_phys to the offset value. The returned Length is ALWAYS 4096.

    (else)

  3. 3. _Obtain the physical address using _CopyPageTable(VirtualAddress/4096, 1, Pte, 0).

    PhysAddr = (Pte & 0xFFFFF000) + (VirtualAddress & 0xFFF).

    Pte is the Page Table Entry as described in the Pentium Processor Users Manual Volume 3.

    The returned Length is ALWAYS 4096.

Based on the above info, one cannot always rely on the returned Length containing the correct length; it may be longer than the actual buffers.

See Also

HW_INITIALIZATION_DATA, SCSI_REQUEST_BLOCK, ScsiPortGetUncachedExtension, ScsiPortGetVirtualAddress