Connecting to the Kernel
We’ll start looking at the structure of network drivers by dissecting
the snull source. Keeping the source code
for several drivers handy might help you follow the discussion and to
see how real-world Linux network drivers operate. As a place to
start, we suggest loopback.c,
plip.c, and 3c509.c, in
order of increasing complexity. Keeping
skeleton.c handy might help as well, although
this sample driver doesn’t actually run. All these files live in
drivers/net, within the kernel source tree.
Module Loading
When a driver module is loaded into a running kernel, it requests resources and offers facilities; there’s nothing new in that. And there’s also nothing new in the way resources are requested. The driver should probe for its device and its hardware location (I/O ports and IRQ line)—but without registering them—as described in Section 9.3 in Chapter 9. The way a network driver is registered by its module initialization function is different from char and block drivers. Since there is no equivalent of major and minor numbers for network interfaces, a network driver does not request such a number. Instead, the driver inserts a data structure for each newly detected interface into a global list of network devices.
Each interface is described by a struct net_device
item. The structures for sn0 and
sn1, the two snull
interfaces, are declared like this:
struct net_device snull_devs[2] = { { init: snull_init, }, /* init, nothing more */ { init: snull_init, ...