VOID
NdisSendPackets(
IN NDIS_HANDLE NdisBindingHandle,
IN PPNDIS_PACKET PacketArray,
IN UINT NumberOfPackets
);
NdisSendPackets forwards a multipacket send request, possibly with associated out-of-band information, to the underlying driver.
Each element in the given array is a pointer to an NDIS_PACKET-type descriptor, and each packet descriptor can have caller-set TimeToSend and/or MediaSpecificInformation and MediaSpecificSize values in its associated NDIS_PACKET_OOB_DATA block. The caller must allocate each such packet descriptor with NdisAllocatePacket.
A protocol can set up this timestamp with the NDIS_SET_PACKET_TIME_TO_SEND and any out-of-band information that accompanies the send request with NDIS_SET_PACKET_MEDIA_SPECIFIC_INFO before it calls NdisSendPackets. The underlying driver retrieves this information with the reciprocal NDIS_GET_PACKET_XXX macros.
If necessary, a protocol also can call NdisSetPacketFlags to set the packet descriptor’s flags with information for the underlying driver.
If the underlying NIC driver does not export a MiniportSendPackets handler, the NDIS library makes a sequence of calls, one for each packet in the supplied array, to that driver’s MiniportSend function. NDIS submits packets individually to an underlying driver’s MiniportSend function in the same order as they arrive in the supplied array.
NDIS submits packet arrays to an underlying driver’s MiniportSendPackets function in the same order as they are passed to NdisSendPackets, but the underlying driver can return a subset of packets in any incoming array to NDIS by setting NDIS_STATUS_RESOURCES in the out-of-band data block for a single array element. When this occurs, NDIS queues that packet and all subsequent packets in the array for resubmission to the MiniportSendPackets function later.
In other words, NDIS always preserves the protocol-determined order of send packets, whether passed in calls to NdisSend or NdisSendPackets, and sees that they are given to the underlying driver in FIFO order. Before a protocol driver calls NdisSendPackets with an array of packet descriptor pointers, the protocol must ensure that the array of pointers has been set up in the same order as the packets should be sent over the wire.
The caller of NdisSendPackets should test the returned status for each packet in such an array individually when its ProtocolSendComplete function is called with the completion Status. While NDIS submits packets for transmission in the FIFO order determined by the sending protocol, underlying drivers can complete such sends in random order.
As soon as a protocol calls NdisSendPackets, it relinquishes ownership of the following:
The protocol regains ownership of these resources, one packet at a time, as its ProtocolSendComplete function is called with each packet descriptor in the array given to NdisSendPackets.
When a packet descriptor is returned to ProtocolSendComplete, it can call NdisReinitializePacket to prepare the packet for reuse after saving the buffer descriptors chained to the packet descriptor with calls to an NdisUnchainBufferAtXxx function. Reusing such a packet descriptor yields better performance than returning the descriptor to driver-allocated packet pool with NdisFreePacket and, then, reallocating it for another send later.
ProtocolSendComplete also can prepare the out-of-band block associated with the given packet descriptor for reuse if the protocol supplies any out-of-band information. Alternatively, the protocol can explicitly reinitialize the members it uses when setting up the packet descriptor for a subsequent send.
An NDIS intermediate driver must repackage each incoming send from still higher level protocols in fresh packet descriptors before passing such a send request to the underlying miniport with NdisSendPackets (or NdisSend).
Callers of NdisSendPackets run at IRQL <= DISPATCH_LEVEL.
MiniportSend, MiniportSendPackets, NdisAllocateBuffer, NdisAllocatePacket, NdisFreePacket, NDIS_PACKET, NDIS_PACKET_OOB_DATA, NdisReinitializePacket, NdisSetPacketFlags, NDIS_SET_PACKET_MEDIA_SPECIFIC_INFO, NDIS_SET_PACKET_TIME_TO_SEND, NdisUnchainBufferAtBack, NdisUnchainBufferAtFront, ProtocolSendComplete