NdisMStartBufferPhysicalMapping

VOID
    NdisMStartBufferPhysicalMapping(
        IN NDIS_HANDLE
 MiniportAdapterHandle,
        IN PNDIS_BUFFER Buffer,
        IN ULONG PhysicalMapRegister,
        IN BOOLEAN WriteToDevice,
        OUT PNDIS_PHYSICAL_ADDRESS_UNIT PhysicalAddressArray,
        OUT PUINT ArraySize
        );

NdisMStartBufferPhysicalMapping sets up a mapping for a busmaster DMA transfer operation.

Parameters

MiniportAdapterHandle
Specifies the handle originally input to MiniportInitialize.
Buffer
Points to a buffer descriptor mapping the virtual range for the transfer. This buffer contains the data to be transferred.
PhysicalMapRegister
Specifies the zero-based index of the map register to be used for the transfer. This value must be no greater than one less than the number of map registers that the driver allocated during initialization with NdisMAllocateMapRegisters.
WriteToDevice
Specifies TRUE when the mapping is used for an outbound transfer from the system through the NIC.
PhysicalAddressArray
Points to a caller-supplied array of NDIS_PHYSICAL_UNIT structures, in which each element is defined as follows:
typedef struct _NDIS_PHYSICAL_ADDRESS_UNIT {
    NDIS_PHYSICAL_ADDRESS PhysicalAddress;
    UINT Length;
} NDIS_PHYSICAL_ADDRESS_UNIT, *PNDIS_PHYSICAL_ADDRESS_UNIT;
 

On return from a successful call to NdisMStartBufferPhysicalMapping, elements in this array specify the mapped logical ranges suitable for downloading to the NIC, with the following members in each element:

PhysicalAddress
Specifies the base physical address for the start of a discrete contiguous range of data to be transferred.
Length
Specifies the number of bytes in the mapped range.
ArraySize
Points to a caller-supplied variable in which NdisMStartBufferPhysicalMapping returns the number of ranges it mapped in the buffer at PhysicalAddressArray. This value is a count of the elements that contain mappings, so the caller can use this count as a bound on the number of physical address ranges it downloads to the NIC subsequently.

Comments

Busmaster NIC drivers call NdisMStartBufferPhysicalMapping in response to send requests originating in protocols bound to the NIC. That is, the buffer descriptor at Buffer usually was chained to a packet input to the NIC driver’s MiniportSend or MiniportSendPackets function.

Every protocol driver is responsible for setting up send packets to suit the limits of the underlying NIC. The NIC driver’s MiniportQueryInformation function already returned these limits in response to certain OID_GEN_XXX requests. Consequently, a miniport need not test incoming send packets for oversized frames or transmit blocks, nor for transmit buffer overflows. For more information about OIDs, see Chapter 5.

A caller of NdisMStartBufferPhysicalMapping must ensure that the array at PhysicalAddressArray is large enough to map the given buffer. A miniport can call NdisGetBufferPhysicalArraySize to determine how many elements are required to map the virtual range specified in the descriptor at Buffer.

For small transfer requests, such as those up to 256K in length, a miniport can achieve higher performance by copying the data to be transmitted into a staging buffer in the shared memory space already allocated with NdisMAllocateSharedMemory or NdisMAllocateSharedMemoryAsync. Because the NIC driver already has mapped virtual and physical addresses for such a shared memory range, it need not call NdisM..BufferPhysicalMapping functions for such small DMA transfers.

Data received by a busmaster NIC is transferred directly into device-accessible buffers within a shared memory block allocated by the miniport. Miniports perform explicit busmaster DMA operations only for transmits.

To transfer packet data for a send request, any miniport basically does the following:

  1. Maps the virtual range containing the data with NdisMStartBufferPhysicalMapping to get mapped device-accessible range addresses for use by its NIC

  2. Downloads the returned physical addresses to the NIC

  3. Calls NdisFlushBuffer and NdisMUpdateSharedMemory if the driver allocated cached memory

  4. Programs the NIC for the transfer operation

  5. Calls NdisMCompleteBufferPhysicalMapping, usually from the MiniportHandleInterrupt function, when the NIC has completed the transfer, which the NIC indicates by a transmit interrupt or, possibly, by a state change discovered by the NIC driver’s polling MiniportTimer function

Any mapping returned by NdisMStartBufferPhysicalMapping is valid only until the miniport calls NdisMCompleteBufferPhysicalMapping. When NdisMCompleteBufferPhysicalMapping returns control, the PhysicalMapRegister specified in the preceding call to NdisMStartBufferPhysicalMapping can be reused in a subsequent DMA operation.

Callers of NdisMStartBufferPhysicalMapping run at IRQL <= DISPATCH_LEVEL.

See Also

MiniportHandleInterrupt, MiniportInitialize, MiniportQueryInformation, MiniportSend, MiniportSendPackets, MiniportTimer, NdisFlushBuffer, NdisGetBufferPhysicalArraySize, NdisMAllocateMapRegisters, NdisMAllocateSharedMemory, NdisMAllocateSharedMemoryAsync, NdisMCompleteBufferPhysicalMapping, NdisMUpdateSharedMemory