NdisMAllocateSharedMemory (Compact 2013)

3/26/2014

This function allocates and maps a host memory range so that it is concurrently available from both the system and a bus master direct memory access (DMA) network adapter.

Syntax

VOID NdisMAllocateSharedMemory(
  NDIS_HANDLE MiniportAdapterHandle,
  ULONG Length,
  BOOLEAN Cached,
  PVOID* VirtualAddress,
  PNDIS_PHYSICAL_ADDRESS PhysicalAddress
);

Parameters

  • MiniportAdapterHandle
    [in] Specifies the handle input to the MiniportInitialize function.
  • Length
    [in] Specifies the number of bytes to allocate.
  • Cached
    [in] Specifies TRUE if the range can be allocated from cached memory. This parameter is ignored if the CachedSharedMem registry key is enabled for the network miniport driver calling this function. For more information about CachedSharedMem, see Network Driver Registry Settings.
  • VirtualAddress
    [out] Points to a caller-supplied variable in which this function returns the base virtual address of the allocation for use by the miniport. If NdisMAllocateSharedMemory cannot satisfy its caller, it returns NULL to indicate that no memory was allocated.
  • PhysicalAddress
    [out] Points to a caller-supplied variable in which this function returns a physical address, usable by the network adapter, that corresponds to that returned at VirtualAddress, or it returns NULL.

Return Value

None

Remarks

NdisMAllocateSharedMemory provides both the mapped virtual address range that the driver uses to access the shared memory block and the NDIS_PHYSICAL_ADDRESS type range that the network adapter uses. A value returned at PhysicalAddress can be doubly mapped by the system. That is, a physical address range described by the value at PhysicalAddress and Length can be a range of mapped logical addresses that do not match the host physical addresses for the allocation in every possible platform.

NdisMAllocateSharedMemory can be called from MiniportInitialize only. You can decide how large an allocation to request based on how the driver writer decides to make the tradeoff between the following performance versus size dilemma:

  • In periods of high network traffic, a miniport cannot maintain high I/O throughput if it runs low on shared memory space for device-accessible data buffers.
    For example, the miniport could be indicating receive buffers in shared memory faster than such buffers are being returned from bound protocols when a flood of receives come in to its network adapter. If all its shared memory space is consumed by outstanding receive buffers, the miniport might have to disable receive interrupts on its network adapter until it has some shared memory space for receive buffers.
  • On the other hand, calling NdisMAllocateSharedMemory with a Length parameter selected to anticipate some maximum transfer demand makes the driver's image larger and its resource usage very uneconomical, except for rare periods of very high I/O demand. Moreover, NdisMAllocateSharedMemory might not give the driver such a large block if insufficient system memory is available, thereby forcing the driver to fail initialization.

NdisMAllocateSharedMemory is the only NdisXxx function that can be called to allocate host memory that is shared between the driver and the network adapter. When it is possible, a miniport driver calls NdisMAllocateSharedMemory with Cached set to TRUE because its request is more likely to succeed. In any platform, non-cached memory is always a scarce system resource. Usually, drivers can obtain larger allocations from cached memory. A miniport driver must allocate its shared memory space from non-cached memory if either of the following is true:

  • The network adapter or miniport writes directly into receive buffers before the miniport indicates the newly received data.
    For example, a network adapter that sets flags in each received frame after it has been transferred must have access to receive buffers in non-cached memory. Otherwise, the miniport could not determine when it should issue a aligned on maintain cache coherency: either the miniport would experience decreased performance by waiting for a fail-safe interval to flush the cached receive buffer or the miniport would make indications in which the frame flags were randomly set.
  • The network adapter transfers some number of received frames sequentially into contiguous physical memory within the shared memory space.
    If such a network adapter transferred incoming frames into contiguous cached memory, its driver cannot maintain data integrity for all such frames when any frame might straddle a cache-line boundary. When the miniport flushed the range for such a frame, it might also flush the cache space that contains some next frame if it was already transferred. This makes that next frame incoherent.

A miniport driver should align the buffers it allocates from shared cached memory on an integral of the host data-cache-line boundary to prevent cache-line tearing during DMA. Cache-line tearing can cause data-integrity problems in the driver or decrease the driver's (and the system's) I/O performance by requiring excessive data-cache flushing to maintain data integrity. MiniportInitializeEx can call NdisMGetDmaAlignment to determine the alignment boundary in the current platform for device-accessible buffers that the driver will set up an allocated range of shared memory.

A miniport driver should set a limit on how much shared memory it can allocate. This limit is driver-specific and should be high enough so that the driver does not run out of buffers. Do not set a limit that is too high, as this could result in a wasteful consumption of shared memory that could reduce system performance.

MiniportInitializeEx might also call NdisSystemProcessorCount before it calls NdisMAllocateSharedMemory if the driver writer decides to allocate a larger shared memory block in multiprocessor devices on the assumption that any SMP device is likely to be a server that has increased network-transfer demands on the network adapter.

If its call to NdisMAllocateSharedMemory fails, MiniportInitializeEx can call again requesting a smaller allocation. However, if MiniportInitializeEx cannot allocate sufficient shared memory for the network adapter, it must release all resources it has already allocated and fail initialization.

If the miniport driver then indicates receives with NdisMIndicateReceiveNetBufferLists, it must allocate some number of buffer descriptors from buffer pool that map the network adapter's receive buffers in the shared memory block.

If the allocated memory is cached and must therefore be flushed on transfers, the miniport driver must call NdisAllocateMdl to allocate an NDIS_BUFFER-type descriptor for the shared memory range. The miniport driver must call KeFlushIoBuffers with this buffer descriptor to perform such a flush.

If a miniport driver calls NdisMAllocateSharedMemory, it must release all outstanding allocations with one or more calls to NdisMFreeSharedMemory when a network adapter is removed, that is, when its MiniportHaltEx function is called.

Requirements

Header

ndis.h

Library

ndis.dll

See Also

Reference

NDIS Shared Memory Interface
MiniportHaltEx
MiniportInitializeEx
MiniportHalt
MiniportInitialize
NdisAllocateBuffer
NdisFlushBuffer
NdisMFreeSharedMemory
NdisMIndicateReceivePacket
NdisMSetAttributes
NdisMSetAttributesEx
NdisSystemProcessorCount
NdisAllocateMdl
NdisMFreeSharedMemory
NdisMIndicateReceiveNetBufferLists
NdisMSetMiniportAttributes
NdisMAllocateNetBufferSGList
Network Driver Registry Settings