The way in which received data is processed depends to some extent on the type of NIC. The process for receiving data is described for each such device type.
Some operations are common to all the devices. These include:
Some miniports, such as a miniport for an Ethernet device, always receive a fixed and known size frame. If the frame size is always the same, the miniport can allocate packets with a chained buffer(s) and the same packets can be reused for receives.
If, however, a miniport controls a NIC on which variable length frames are received, the size of a packet needed to handle a receive can vary from one receive to the next.
If a miniport must handle variable-length receives, it must do the following:
Buffers that are unchained from a packet descriptor should be kept in a free list to ensure they don’t get “lost” and so they are available when needed.
When a packet or packets is received, the miniport does the following:
If the miniport calls NdisMAllocateSharedMemoryAsync to allocate a buffer, it will be called at its MiniportAllocateComplete function when the allocation is complete.
A miniport for a PIO device reads data from the NIC ports using NdisRawReadPortXxx using ports previously claimed with NdisMRegisterIoPortRange. Typically such a device indicates the lookahead portion of a received packet to bound protocol drivers by calling a filter-specific NdisXxxIndicateReceive function and transfers the rest of the data to interested protocol drivers in its MiniportTransferData function. After the data is transferred, the data can be overwritten by new data after receive interrupts are re-enabled.
A miniport for a PIO NIC should insure that new data is not missed because of the time delay in transferring current data to an upper layer protocol driver. If a NIC has a relatively small on-board FIFO buffer, the miniport can preallocate a buffer in its MiniportInitialize function and then stage the received data into this buffer to be indicated up. Staging is done to try to keep the FIFO as empty as possible and available for new incoming data.
Alternatively, the miniport can indicate up data copied directly from the NIC port and move the rest of the received data directly from the NIC when its MiniportTransferData is called. This receive technique incurs a delay equal to the time between when the received data was indicated up by calling NdisXxxIndicateReceive and when MiniportTransferData is called and moves the received data into the buffer provided to MiniportTransferData.
If the miniport calls NdisMIndicateReceivePacket, it transfers the data into a buffer(s) chained to a preallocated packet before it makes the call.
A miniport that manages a NIC with on-board memory typically transfers the received data in MiniportTransferData directly from the NIC to a buffer supplied in the MiniportTransferData call. Like a PIO NIC miniport, the miniport can stage the receive if there is a possibility that new data will be lost because of the latency incurred by the direct transfer from the NIC to the protocol driver-supplied buffer(s).
The miniport calls NdisMXxxIndicateReceive to indicate up an amount of data equal to the lookahead size or, if the buffer is small and the miniport has the complete buffer, it indicates up the complete buffer. MiniportTransferData calls NdisMoveFromMappedMemory to transfer data from the NIC’s on-board memory to the protocol driver’s packet or to a staging buffer. After the data is transferred, the miniport can reenable interrupts so that new data can be received.
If the miniport calls NdisMIndicateReceivePacket, it transfers the data into a buffer(s) chained to a preallocated packet before it makes the call.