NdisMIndicateReceivePacket function
Note NDIS 5. x has been deprecated and is superseded by NDIS 6. x. For new NDIS driver development, see Network Drivers Starting with Windows Vista. For information about porting NDIS 5. x drivers to NDIS 6. x, see Porting NDIS 5.x Drivers to NDIS 6.0.
NdisMIndicateReceivePacket notifies NDIS that an array of received packets is available to be forwarded to the appropriate bound protocol driver(s).
Syntax
VOID NdisMIndicateReceivePacket(
_In_ NDIS_HANDLE MiniportAdapterHandle,
_In_ PPNDIS_PACKET ReceivePackets,
_In_ UINT NumberOfPackets
);
Parameters
MiniportAdapterHandle [in]
Specifies the handle originally input to MiniportInitialize.ReceivePackets [in]
Pointer to an array of packet descriptor pointers, with each descriptor set up by the caller to specify the received data.NumberOfPackets [in]
Specifies how many pointers are in the array at ReceivePackets. The value must be at least one.
Return value
None
Remarks
Drivers of bus-master DMA NICs are most likely to show significant gains in performance by making multipacket receive indications with NdisMIndicateReceivePacket. However, drivers that indicate out-of-band data, such as packet priority and/or timestamps, with receive packets can also call this function with a single packet at a time. When a miniport driver calls NdisMIndicateReceivePacket, NDIS passes each pointer at ReceivePackets separately, in the miniport driver-determined order, to the ProtocolReceivePacket function(s) of bound protocol(s) that export this function. To other bound protocols, NDIS passes each packet pointer to the ProtocolReceive function(s).
If the miniport driver did not designate its NIC's medium as a type for which the system supplies a filter package in response to the OID_GEN_MEDIA_IN_USE query, NDIS forwards that driver's receive indications to all bound protocol drivers that export a ProtocolReceivePacket function. Otherwise, NDIS automatically applies the appropriate filter library to the miniport driver's receive indications.
Any caller of NdisMIndicateReceivePacket must first set up the packet array, as follows:
Each element is the pointer to a packet descriptor, which the caller must allocate from packet pool. Each packet descriptor has 4*sizeof(PVOID) in its ProtocolReserved section. On 32-bit systems, four pointer's worth of ProtocolReserved space equals 16 bytes. On 64-bit systems, four pointer's worth of ProtocolReserved space equals 32 bytes.
All buffer descriptors chained to such a packet descriptor must be allocated from buffer pool. The miniport driver must call NdisAdjustBufferLength with any buffer descriptor mapping a receive buffer on the NIC that contains less received data than the full range of the receive buffer so that the buffer descriptor will map only the received data for the indication. (The NIC driver must readjust the mapping with NdisAdjustBufferLength when it regains ownership of such a buffer descriptor, as well.)
The first buffer in the packet must contain the amount of data specified by the lookahead setting plus the data size of the MAC header. The miniport driver receives the lookahead setting in a set to OID_GEN_CURRENT_LOOKAHEAD. If the total packet size including the MAC header is less than the lookahead setting plus the MAC header size, the first buffer must contain the entire packet.
If the miniport driver indicates timestamps for received packets, it must set the TimeReceived and/or TimeSent members in the NDIS_PACKET_OOB_DATA associated with the packet descriptor, using the NDIS_SET_PACKET_TIME_RECEIVED and/or NDIS_SET_PACKET_TIME_SENT macros. It can call NdisGetCurrentSystemTime once to set the receive timestamp for all packets of a particular packet array.
The HeaderSize in the out-of-band data block must match the header size of each received packet for the medium. For example, a driver that selects Ethernet as its preferred medium initializes the NDIS_PACKET_OOB_DATA block HeaderSize to 14 when it allocates the packet descriptor. A driver should use the NDIS_SET_PACKET_HEADER_SIZE macro to set the HeaderSize.
If the driver indicates additional out-of-band information with receives, it must set the SizeMediaSpecificInfo to the number of bytes of information supplied in the caller-allocated buffer at MediaSpecificInformation. The miniport driver can use the NDIS_SET_PACKET_MEDIA_SPECIFIC_INFO macro to set these values. Otherwise, SizeMediaSpecificInfo should be zero, and MediaSpecificInformation should be NULL.
The miniport driver can set the Status member of the out-of-band data block to NDIS_STATUS_RESOURCES if it needs to retain ownership of the packet descriptor and buffer descriptors of some element in a particular indication. Setting NDIS_STATUS_RESOURCES forces NDIS to indicate each such packet, one at a time, to bound protocols' ProtocolReceive functions, thereby forcing each protocol to copy the packet data and release each packet to be returned back to the miniport driver.
A deserialized miniport driver must save the Status member of the out-of-band data block in a local variable before indicating up the packet descriptor. As explained in more detail below, when NdisMIndicateReceivePacket returns, a deserialized miniport driver must check the saved packet Status to determine whether it can immediately reclaim the packet descriptor and the associated buffers.
If a serialized miniport driver does not set a packet's Status member to NDIS_STATUS_RESOURCES, the call to NdisMIndicateReceivePacket gives interested protocols exclusive, read-only access to the buffers chained to each packet. The miniport driver regains ownership of the packet descriptor and the associated buffers as follows:
If the Status in the out-of-band data block is set to NDIS_STATUS_SUCCESS on return from NdisMIndicateReceivePacket, the miniport driver immediately regains ownership of the packet descriptor and all buffers chained to the packet. It can prepare these descriptors for reuse in subsequent receive indications.
If the Status is set to NDIS_STATUS_PENDING on return from NdisMIndicateReceivePacket, the miniport driver regains ownership of the packet descriptor and all buffers chained to the packet when NDIS subsequently calls the miniport driver's MiniportReturnPacket function. It can then prepare these descriptors for reuse in subsequent receive indications.
A serialized miniport driver should use NDIS_GET_PACKET_STATUS to determine whether it has regained ownership of indicated packets when NdisMIndicateReceivePacket returns control.
A deserialized miniport driver must not examine the Status of indicated packets on return of NdisMIndicateReceivePacket. Instead, a deserialized miniport driver must save a packet's Status in a local variable before indicating up the packet descriptor. When NdisMIndicateReceivePacket returns, the miniport driver should check the saved packet Status. If the miniport driver set the packet's Status to NDIS_STATUS_RESOURCES before indicating up the packet descriptor, it should reclaim the packet descriptor immediately after NdisMIndicateReceivePacket returns, preferably by calling its own MiniportReturnPacket function. In this case, NDIS does not call the miniport driver's MiniportReturnPacket function to return the packet descriptor. If the miniport driver set the packet's Status to NDIS_STATUS_SUCCESS before indicating up the packet descriptor, the miniport driver must not reclaim the packet descriptor until NDIS subsequently returns the packet descriptor to the miniport driver's MiniportReturnPacket function.
When the miniport driver regains ownership of an indicated packet descriptor, it can prepare the associated out-of-band data block for reuse by passing the pointer returned by NDIS_OOB_DATA_FROM_PACKET to NdisZeroMemory. As an alternative, the miniport driver can simply reset the relevant member(s) at the subsequent receive with the NDIS_SET_PACKET_ XXX macro(s) or with the pointer returned by NDIS_OOB_DATA_FROM_PACKET.
A miniport driver must not pass a packet descriptor pointer to NdisZeroMemory. Doing this destroys the packet descriptor, rendering it unusable for subsequent indications. To clear the associated out-of-band data block, the driver must pass the pointer returned by NDIS_OOB_DATA_FROM_PACKET.
Packet arrays passed to NdisMIndicateReceivePacket can be allocated on the stack, which cannot be paged out in the NDIS library's receive-indication code path.
When NDIS calls the ProtocolReceive function of a driver that exports a ProtocolReceivePacket function, ProtocolReceive can call NdisGetReceivedPacket and NDIS_GET_ORIGINAL_PACKET to retrieve the out-of-band information associated with an incoming packet that was indicated as part of a packet array.
Any miniport driver that calls NdisMIndicateReceivePacket must indicate full packets. Consequently, such a driver has no MiniportTransferData function.
If a miniport driver that is running on a Microsoft Windows XP or Windows 2000 system indicates packets that consist of multiple chained NDIS_BUFFER structures, the driver must do one of the following to ensure that the host stack properly processes such packets:
When responding to a query of OID_GEN_MAC_OPTIONS shortly after driver initialization, the driver must not set the NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA flag.
Before calling NdisMIndicateReceivePacket, the driver must set the Status member of the NDIS_PACKET_OOB_DATA structure that is associated with the packet descriptor to NDIS_STATUS_RESOURCES.
Note A miniport driver that is running on a Windows Server 2003 or later system does not have to handle the preceding situation.
A miniport driver must release any spin lock that it is holding before calling NdisMIndicateReceivePacket.
Serialized callers of NdisMIndicateReceivePacket must run at IRQL = DISPATCH_LEVEL. Deserialized callers of NdisMIndicateReceivePacket must run at IRQL <= DISPATCH_LEVEL.
Requirements
Target platform |
Desktop |
Version |
Not supported for NDIS 6.0 drivers in Windows Vista. Use NdisMIndicateReceiveNetBufferListsinstead. Supported for NDIS 5.1 drivers in Windows Vista and Windows XP. |
Header |
Ndis.h (include Ndis.h) |
IRQL |
See Remarks section. |
See also
NdisMAllocateSharedMemoryAsync