The MiniportSendPackets function is required for drivers that do not have a MiniportSend, MiniportWanSend, or MiniportCoSendPackets function. MiniportSendPackets transfers some number of packets, specified as an array of packet pointers, over the network.
VOID
MiniportSendPackets(
IN NDIS_HANDLE MiniportAdapterContext,
IN PPNDIS_PACKET PacketArray,
IN UINT NumberOfPackets
);
Declared in Ndis.h. Include Ndis.h.
If a driver registers both MiniportSendPackets and MiniportSend functions when it initializes, NDIS always calls its MiniportSendPackets function. If a driver registers both MiniportSendPackets and MiniportCoSendPackets functions, NDIS calls its MiniportCoSendPackets function when any bound protocol calls NdisCoSendPackets.
The input packet descriptor pointers have been ordered according to the order in which the packets should be sent over the network by the protocol driver that set up the packet array. The NDIS library preserves the protocol-determined ordering when it submits each packet array to MiniportSendPackets.
Consequently, MiniportSendPackets should transmit each packet in any given array sequentially. MiniportSendPackets can call NdisQueryPacket to extract information, such as the number of buffer descriptors chained to the packet and the total size in bytes of the requested transfer. It can call NdisGetFirstBufferFromPacket, NdisGetFirstBufferFromPacketSafe, NdisQueryBuffer, NdisQueryBufferSafe, or NdisQueryBufferOffset to extract information about individual buffers containing the data to be transmitted.
MiniportSendPackets can retrieve any protocol-supplied out-of-band information associated with each packet by using the relevant NDIS_GET_PACKET_TIME_TO_SEND and NDIS_GET_PACKET_MEDIA_SPECIFIC_INFO macros.
Each protocol driver must set up packet arrays with packet descriptors that are fully set up to be passed by the underlying driver’s MiniportSendPackets function to its NIC. That is, the protocol is responsible for determining what is required, based on the medium type selected by the miniport driver to which the protocol bound itself. However, a protocol can supply packets shorter than the minimum for the selected medium, which MiniportSendPackets must pad if its medium imposes a minimum-length requirement on transmits.
Any NDIS intermediate driver that layers itself between a higher-level protocol and an underlying NIC driver has the same responsibility as any protocol driver to set up packets according to the requirements of the underlying miniport driver and its selected medium. Such an intermediate driver must repackage each incoming send packet in a fresh packet descriptor that was allocated by the intermediate driver.
MiniportSendPackets can use only the eight-byte area at MiniportReserved within the NDIS_PACKET structure for its own purposes. Consequently, an NDIS intermediate driver that forwards send requests to an underlying NIC driver must repackage the packets given to its MiniportSendPackets function in fresh packet descriptors, which the intermediate driver allocates from packet pool, so that the underlying miniport driver has a MiniportReserved area it can use.
If the underlying driver’s MiniportQueryInformation function set the NDIS_MAC_OPTION_NO_LOOPBACK flag when the NDIS library queried the OID_GEN_MAC_OPTIONS, the miniport driver must not attempt to loop back any packets. The NDIS library provides software loopback support for such a driver.
Whether the driver is serialized or deserialized determines how its MiniportSendPackets function handles the completion of input packet descriptor(s) when this driver function is called.
The MiniportSendPackets function of a serialized driver sets one of the following values in the Status member of the NDIS_PACKET_OOB_DATA block associated with an input packet descriptor:
When MiniportSendPackets sets this value for a packet in the input array, the NDIS library assumes all remaining packets in the array have the same status set, so NDIS requeues the associated packets in the same order, which preserves the protocol-determined ordering of the packet array. NDIS reflects this status to the protocol as NDIS_STATUS_PENDING for this packet and for all remaining packets in the given array.
When MiniportSendPackets returns control, a serialized driver can no longer access anything in the given packet array with the following exceptions:
After the driver calls NdisMSendComplete with the final status of the transmit operation, ownership of the given packet descriptor, out-of-band data block, and associated buffers reverts to the allocating protocol. A miniport driver should never return NDIS_STATUS_RESOURCES for a packet it passes to NdisMSendComplete.
Setting NDIS_STATUS_RESOURCES for an incoming packet causes NDIS to requeue the associated packet and those specified by all remaining array elements for subsequent resubmission to the MiniportSendPackets function of a serialized driver. NDIS assumes that a subsequent call to NdisMSendResourcesAvailable or NdisMSendComplete, whichever occurs first, indicates that such a driver's MiniportSendPackets function is ready to accept more packets for transmission. NDIS preserves the original ordering of returned array elements when it resubmits them as a packet array to MiniportSendPackets.
The MiniportSendPackets function of a serialized miniport driver runs at IRQL = DISPATCH_LEVEL.
The NDIS library ignores the OOB block in all packet descriptors it submits to the MiniportSendPackets functions of deserialized drivers and assumes that all deserialized miniports will complete each packet descriptor input to their MiniportSendPackets functions asynchronously with NdisMSendComplete. Consequently, such a deserialized driver's MiniportSendPackets function usually ignores the Status member of the NDIS_PACKET_OOB_DATA block, but it can set this member to the same status as it subsequently passes to NdisMSendComplete.
Rather than relying on NDIS to queue and resubmit send packets whenever MiniportSendPackets has insufficient resources to transmit the given packets, a deserialized miniport driver manages its own internal packet queuing. Such a driver is responsible for holding incoming send packets in its internal queue until they can be transmitted over the network and for preserving the protocol-determined ordering of packet descriptors incoming to its MiniportSendPackets function. A deserialized miniport driver must complete each incoming send packet with NdisMSendComplete, and it cannot call NdisMSendResourcesAvailable.
A deserialized miniport driver should never pass STATUS_INSUFFICIENT_RESOURCES to NdisMSendComplete with a protocol-allocated packet descriptor that was originally submitted to its MiniportSendPackets function. Such a returned status effectively fails the send operation requested by the protocol, and NDIS would return the packet descriptor and all associated resources to the protocol that originally allocated it.
The MiniportSendPackets function of a deserialized miniport driver can be called at any IRQL <= DISPATCH_LEVEL. The MiniportSendPackets function of a deserialized driver is responsible for synchronizing access to its internal queues of packet descriptors with the driver's other MiniportXxx functions that also access the same queues.
MiniportCoSendPackets, MiniportInitialize, MiniportQueryInformation, NdisAllocatePacket, NdisGetBufferPhysicalArraySize, NdisGetFirstBufferFromPacket, NdisGetFirstBufferFromPacketSafe, NdisGetNextBuffer, NDIS_GET_PACKET_MEDIA_SPECIFIC_INFO, NDIS_GET_PACKET_TIME_TO_SEND, NdisMoveMemory, NdisMoveToMappedMemory, NdisMSendComplete, NdisMSendResourcesAvailable, NdisMSetupDmaTransfer, NdisMStartBufferPhysicalMapping, NDIS_OOB_DATA_FROM_PACKET, NDIS_PACKET, NDIS_PACKET_OOB_DATA, NdisQueryBuffer, NdisQueryBufferOffset, NdisQueryBufferSafe, NdisQueryPacket, NdisSendPackets, NdisZeroMemory