"Copyright notice: Reprint please keep Source: Blog.csdn.net/gentleliu. E-mail: shallnew*163.com "
The NIC driver inserts a data structure into a global network device list for each new interface. Each interface is described by a structure net_device item, which is defined in <linux/netdevice.h>. The structure must be dynamically allocated.
The kernel function for this allocation is Alloc_netdev, which has the following prototypes:
struct Net_device *alloc_netdev (int sizeof_priv, const char *name, void (*setup) (struct net_device *));
Sizeof_priv is the size of the drive's "private data" area; name is the name of the interface; this name can have a printf-style%d in it. The kernel replaces this%d with the next available connection number. Setup is a pointer to an initialization function that is called to set the remainder of the net_device structure.
The network subsystem provides some help functions for various interfaces, wrapped in Alloc_netdev. The most common is alloc_etherdev, defined in <linux/etherdevice.h>, and other network device interfaces, such as Alloc_fcdev (defined in <linux/fcdevice.h>) for Fiber-channel device, Alloc_fddidev (<linux/fddidevice.h>) is an FDDI device, or Aloc_trdev (<linux/trdevice.h>) is a token ring device.
The Alloc_etherdev function prototype is:
struct Net_device *alloc_etherdev (int sizeof_priv);
Where Sizeof_priv is the size of the "private data" area of the drive; This function assigns a network device to use eth%d as the parameter name. It provides its own initialization function (Ether_setup) to set several Net_device fields, using the appropriate values for the Ethernet device. Therefore, there is no driver-provided initialization function for Alloc_etherdev;
The initialization function that he provides himself is Ether_setup:
/** * Ether_setup-setup Ethernet Network device * @dev: Network device * Fill in the ' fields ' of the device structure with Ethernet-generic values. */void ether_setup (struct net_device *dev) { dev->header_ops = e_header_ops; Dev->type = arphrd_ether; Dev->hard_header_len = Eth_hlen; Dev->mtu = Eth_data_len; Dev->addr_len = Eth_alen; Dev->tx_queue_len = +; /* Ethernet wants good queues */ dev->flags = iff_broadcast| Iff_multicast; memset (Dev->broadcast, 0xFF, Eth_alen);}
Export_symbol (Ether_setup);
In fact, the function is only responsible for the default values in some Ethernet ranges. The setup function provided by the general Alloc_netdev function also calls the function to set these default values.
In fact, whether you use the Alloc_netdev function or the Alloc_etherdev function does not just set these default values enough.
Since it is to write network device drivers, it is necessary to complete the basic functions of the NIC: Send and receive data packets, statistics network card data, etc., so generally also set the structure of these functional function pointers, and these functions are the network device drivers need to implement the basic functions. So if you use function Alloc_netdev to allocate space, then the setup function is generally implemented as:
{ ether_setup (dev); #if (Linux_version_code >= kernel_version (2,6,29)) dev->netdev_ops = &xxx_netdev_ops; #else Dev->open = xxx_open; Dev->stop = xxx_stop; Dev->hard_start_xmit = Xxx_tx; Dev->get_stats = xxx_stats; dev->change_mtu = XXX_CHANGE_MTU; ... #endif }
If you use the Alloc_etherdev function assignment, you will need to set the following after the function:
#if (Linux_version_code >= kernel_version (2,6,29)) dev->netdev_ops = &xxx_netdev_ops; #else Dev->open = xxx_open; Dev->stop = xxx_stop; Dev->hard_start_xmit = Xxx_tx; Dev->get_stats = xxx_stats; dev->change_mtu = XXX_CHANGE_MTU; ... #endif
In fact, the difference is that the Alloc_etherdev function automatically calls the Ether_setup function by default and automatically assigns a network device to use eth%d as the parameter name, and the function Alloc_netdev need to pass in parameters to set them.
After the net_device structure is initialized, pass this structure to the Register_netdev function to complete the registration.
Then all you have to do is implement the previously registered functions, and the specific analysis of the transceiver functions will be explained in detail later.