A.4.1.1 Handling Transmit Data

When writing a NIC driver, ensure that any data the card reads is actually present in physical memory before the read begins. Have your driver flush cached memory for transmit data by calling NdisFlushBuffer. The cache is divided into blocks of a fixed cache fill size, and the driver should flush an entire block at a time. The driver does not need to flush all cached data immediately after writing it, but should flush it before accessing the network interface card. Since cache line tearing is not a problem for transmit data, the driver can flush the data without concern for cache fill size.

For example, the NIC driver usually gives a busmastering network interface card the physical addresses of packet segments. Most of these segments are from the NDIS_PACKET structure that a transport driver passes to MacSend in the NIC driver. The NIC driver describes the segments to the network interface card, and then releases the packet to the card for transmission on the network. The driver must flush the data at some point before it relinquishes the packet, but the actual timing is not important. The NIC driver can flush cached data upon entry to MacSend, or immediately before it releases the packet.

When using noncached memory for transmit data, make sure the NIC driver calls NdisWriteRegisterXxx. This function ensures that the data is in physical memory before it returns. Calling the function allows sequential writes to memory in the order in which they occur and consecutive writes to the same memory location, resulting in two distinct writes to memory. This is especially important when the driver is accessing memory that corresponds to registers on the network interface card. For example, if the reset register requires the NIC driver to write first a zero and then a one before a reset, the driver must not merge these two writes.

 
Note  Generally it is preferable to allocate cached memory for transmit data, since the operating system can have trouble allocating noncached memory. Always assume that memory passed in from a transport driver is cached. Have the NIC driver use cached memory as memory to which it writes only rarely, and flush the memory when writing. To simplify its logic, the driver may use noncached memory as memory to which it writes often.