Ethernet Drivers: What to Do When Networking Isn't Working
By Hank Sackett -- <hank@be.com>

You've just launched a browser and you're waiting for
it to come up. And waiting. And waiting. Could there be
a network fault? Yes, and it could be at any point between
you and your destination host.

To check whether networking *is* working, you can look at
it from many viewpoints. A packet sniffer on a hub sees
all the traffic in that collision domain, which is often
helpful. The Ethernet driver has another point of view,
and to use it, I've added a debugger command to the
AMD AM79C978 driver, which you'll receive in the release
after 4.5.2.

Case in point: There was a machine configured with an IP
address that looked OK, but wasn't. From the serial
debugger:

kdebug> homelan R T

This toggles the display of received and transmitted frames on or off.
It showed that an ARP request was received by the driver
and passed up to the protocols above, but no response was
transmitted back. This was the clue I needed to realize
the IP address received didn't match the one configured.

The command "homelan I" traces interrupt activity,
which will be absent if there was a problem assigning
the IRQ, for example because of a problem with the
BIOS settings.

Another view of networking is in the traffic between
the driver across the PCI bus and the network interface
card. "homelan p" will toggle PCI IO tracing on and off.
You're probably interested in this level of detail only
if you're writing device drivers. If you are, you're in
luck, because you'll find a framework for writing a PCI
Ethernet driver at

<ftp://ftp.be.com/pub/samples/drivers/ethertemplate.zip>

To use it, first replace the string "AcmeEthernet" with
the name of your new driver. Assign the vendor and device
ID, which you can find in the Devices preference. Next,
decide if you're using memory or port PCI I/O, and set
#define IO_PORT_PCI_ACCESS. From a terminal window, the
commands "poke" and "pci" will show the addresses that
the hardware has assigned. At this point, refer to the
hardware-specific reference and read up a register with
some recognizable constant, like the chip revision number.
Next, get the Mac address -- usually from a serial ROM.
Initialize the hardware and enable hardware interrupts.

An interrupt from hardware causes the driver's interrupt
service routine to be called. But which hardware generated
the interrupt? It's crucial that the Ethernet driver be
able to accurately determine the source of the interrupt,
and return B_INVOKE_SCHEDULER or BE_UNHANDLED_INTERRUPT
correctly. If the Ethernet driver returns B_INVOKE_SCHEDULER
to a video card's interrupts it will "steal" the interrupt,
and the likely outcome will be a frozen screen. Returning
BE_UNHANDLED_INTERRUPT to an interrupt that was actually
generated by the NIC hardware will cause the kernel to
be left holding an unclaimed interrupt. As a result the
kernel will disable all interrupts on the line until
a timeout expires, and a lot of packets will be dropped.

Getting the transmitter and receiver to work are the next
two steps. A ping flood from a faster machine on an
isolated network to the driver under development, with
the "AcmeEthernet N" sequence number trace enabled, will
tell how well the driver performs under load. Look for
dropped frames and frames out of sequence.

There are lots of changes currently underway in the Be
networking code; you should expect to make revisions and
source code changes to stay current and take advantage
of the new features. Don't let that keep you from
writing a driver, but keep reading the newsletters.

Until next time, happy networking.
