Receive

It's important to mention that unlike io-net, a native io-pkt driver doesn't create a high-priority receive thread to handle interrupts.

Packet reception in io-pkt starts with an interrupt from the hardware, which io-pkt initially handles, so let's look at that first.

If you look at speedo.c, you'll see two functions that can be called by io-pkt: speedo_isr() and speedo_isr_kermask().

A driver can either choose to use the simple kernel masking method of acknowledging interrupts, or it can choose to use the more elegant "real" ISR technique. The major advantage of using the real ISR is that when interrupts are shared between different devices — a bad idea, generally — far less interrupt latency will be experienced, if both devices' interrupt handlers do "the right thing" with real ISR handlers, and check for and mask their interrupt sources in hardware. If the interrupt isn't shared between different devices, the advantage of kermask versus real ISR isn't very noticeable.

A complete discussion of system interrupts in QNX Neutrino is outside the scope of this document. Suffice it to say that with io-pkt, a driver may choose one method or the other, possibly via a command-line option.

Either way, after an interrupt occurs, io-pkt calls the driver's speedo_process_interrupt() function, which loops, checking the hardware registers to see why the interrupt occurred. One of the functions it calls is speedo_receive(), which is located in receive.c. The speedo_receive() function scans through all filled rx descriptors, passing their mbufs up to io-pkt via the ifp->if_input() function. Note that it calls into io-pkt to get a new mbuf via the m_getcl_wtp() function — unlike some io-net drivers, it doesn't attempt to maintain its own internal cache of buffers.