4.6.2 Single-Packet Receives

During initialization, MiniportQueryInformation is called to determine the miniport’s or NIC’s operational characteristics, including the minimum size of lookahead buffer it will indicate up. It must indicate up at least this minimum amount of data but it can indicate up more if more data is available on the NIC. For instance, a DMA adapter transfers all the data directly into memory, so the miniport for such a device usually indicates the complete received buffer up, allowing a protocol driver to copy the buffer on the indication without having to make a call to NdisTransferData to get the rest of the data.

On the other hand, miniports that manage PIO devices pass a minimum lookahead buffer up to protocol drivers, and the rest of the data is not read until the miniport gets called at its MiniportTransferData function. Because transferring data in this manner is slow, such a miniport optimizes for the case that no protocol accepts the packet and the minimum number of protocols request calls to MiniportTransferData.

A miniport that calls NdisXxxIndicateReceive must have a MiniportTransferData function and must be prepared to be called to copy incoming data into a packet with chained buffers passed down by a protocol driver. MiniportTransferData is called in the context of the miniport’s NdisMXxxIndicateReceive call. After NdisMXxxIndicateReceive returns control, the miniport can receive new data; that is, it can reenable receive interrupts.

MiniportTransferData is passed a packet descriptor that can specify a single buffer or a chain of buffers. The miniport must divide up the incoming data into these buffers. If the buffer(s) supplied by the protocol driver are insufficient, the miniport should fail the transfer call with an appropriate status. The protocol driver should not make this mistake because the miniport indicates the total size of the incoming network packet in its NdisMXxxIndicateReceive call. Data transfer can complete synchronously if all the data is transferred inside MiniportTransferData or MiniportTransferData can return NDIS_STATUS_PENDING. If the miniport returns a pending status, it must later call NdisMTransferDataComplete when all the data has been transferred. Again, the miniport must not reenable interrupts until the transfer of data is complete so that the current received data is not overwritten by an incoming receive.

A miniport must periodically make a call to NdisMXxxReceiveComplete. This call causes NDIS to call bound protocol drivers’ ProtocolReceiveComplete functions. This notifies a protocol driver that it can process the data it has received but not yet processed fully, such as making indications to clients. A recommended strategy for a miniport is to make this call in its MiniportHandleInterrupt function every ten receives or before exiting MiniportHandleInterrupt if fewer than ten receives are processed.