3.1.3.4  Choosing a Receive Function

Miniports choose between two methods of passing incoming packets to upper layers.

·Miniports call NdisMIndicateReceivePacket to pass a pointer to an array containing one or more pointers to one or more received packets. When a miniport indicates an array of packet pointers, entire network packet(s) are passed up to the receiving layer. That is, when the miniport calls NdisMIndicateReceivePacket, it makes the entire network packet available to upper layers including any OOB data associated with each packet descriptor. When NdisMIndicateReceivePacket returns, ownership of the array that contains the pointers to packet descriptors reverts to the miniport. Actual packet descriptors and the miniport-allocated resources they describe may or may not be returned. Any upper layer can choose to keep a packet and return it later, consume the data in the packet and return it immediately, or return the packet immediately unread because it is not interested in the data. This means that when NdisMIndicateReceivePacket returns, the miniport must not reference any of the individual packets whose status in the OOB data is set to NDIS_STATUS_PENDING.

·Miniports call a filter-specific NdisMXxxIndicateReceive with a pointer to a lookahead buffer. An interested protocol can either copy the packet (if the packet is small and the entire packet is indicated up) or call NdisTransferData from its ProtocolReceive function and let the MiniportTransferData function copy the entire packet.

If a miniport indicates an array of packets by calling NdisMIndicateReceivePacket, ownership of the packets can pass to the receiving protocol driver. Such a miniport must provide a MiniportReturnPacket function. MiniportReturnPacket will be called for each packet passed up to a protocol driver for which the protocol driver returns NDIS_STATUS_PENDING in order to return ownership of the packet resources to the miniport after the protocol has consumed the data. Any miniport that supports multipacket receive indications:

·Must allocate enough packet descriptors and insure that it has available buffers while waiting for an upper layer to return previously indicated packets. Packet descriptors must be allocated from packet pool.

·Must allocate enough memory to contain one or more complete network packets and buffer descriptors mapping the memory so that it can pass a packet or packets to upper layers. Miniports that force an interested protocol to copy received data only need a buffer to hold the received data or lookahead buffer, which in some cases is buffer space on the NIC. Buffer descriptors must be allocated from buffer pool.

If a miniport uses NdisMXxxIndicateReceive to indicate a receive packet up to an upper-layer, that miniport must provide a MiniportTransferData function. The miniport retains ownership of the memory containing the indicated data and MiniportTransferData will be called to move the received data from the miniport’s buffer to a packet supplied by the receiving protocol driver. The buffer containing the received data can be either a staging buffer or can be buffer space on the NIC.

A miniport chooses to indicate an array of packets by calling NdisMIndicateReceivePacket

·If its NIC is a high performance busmaster DMA device that receives data in a ring of buffers for which multiple packets can be allocated, filled, and indicated up

·Or, the miniport supports passing media-specific information with incoming packets

In this case, the miniport must pass an entire packet, described by a packet descriptor with an associated OOB data block, up to an interested protocol(s) since the media-specific information is stored in the OOB block. A miniport for a slow NIC that wants to pass media-specific information may choose the multipacket receive technique but indicate up one-element packet arrays to avoid queuing receives.