Transmit

Now look at trunk/sys/dev_qnx/speedo/transmit.c. When io-pkt wants the driver to transmit an mbuf, it calls the driver's speedo_start() function, which is registered in speedo_init().

Note: Don't be confused by the *_start() name — it has nothing to do with the *_stop() function, which io-pkt may also call, to shut down.

The speedo_start() function checks the ifp flags (see above) and if the driver isn't running, it immediately returns.

Next, it loops, checking to see if there are any transmit descriptors free. If so, it calls the IFQ_DEQUEUE() macro to get the next queued mbuf for transmission. Each data fragment of the mbuf has its physical address loaded into a tx descriptor, and the cache flushed.

Note that as in io-net, the driver is free to defragment the packet, if it thinks it's too fragmented.

Next, the hardware registers are written to, to tell the hardware that there's a new packet ready for transmission.

Note that at the very end of the speedo_start() function, it calls the io-pkt NW_EX_LK() macro to unlock the mutex that io-pkt locked before it called the driver's *_start() function.

At the end of transmit.c is the speedo_transmit_complete() function, which is called from various places in the driver to harvest descriptors of completed transmissions. A very important difference from io-net is that when the driver has completed transmission of the packet, it simply calls m_free() and releases the mbuf; it doesn't attempt to return the packet to the protocol, as with io-net.