Learning kernel-Linux NIC Driver Analysis

Source: Internet
Author: User
Article Title: kernel learning-Linux NIC Driver Analysis. Linux is a technology channel of the IT lab in China. Includes basic categories such as desktop applications, Linux system management, kernel research, embedded systems, and open source.

Learning should first simplify the problem and complicate the problem. Starting from the very beginning, we began to deal with complicated problems, which would inevitably make people feel stunned and stretched. The same is true for reading Linux Nic drivers. The long source code is mixed with unfamiliar variables and symbols, and it is a matter of course. Don't worry, there is always a solution to things. First, we cut out some code that we can't manage, leave the necessary part, and master the framework. Naturally, what else will happen will come to the fore, this is my experience.

The Linux NIC driver code is usually around 3000 lines. The amount of code and the amount of knowledge it expresses are undoubtedly huge. Can we shorten the amount of code, it makes our learning easier. With the unremitting efforts of the author, we have reduced the network device to more than 600 lines while still working properly, we cut out the functions that are currently unavailable. In this way, things are much simpler, and there is really a framework left. Next we will analyze this executable framework.

I will not list all the Function Code involved in the kernel used in the following analysis. However, please refer to the specific file for reference.

First, let's look at the device initialization. After we compile our program correctly, we need to load the generated target file to the kernel, we will first ifconfig eth0 down and rmmod 8139too to uninstall the NIC Driver in use, and then insmod 8139too. o loads our driver (8139too. o is the target file generated by our compilation ). Just as the C program has the main function main (), the module also has the first function to be executed, namely module_init (rtl8139_init_module); in our program, rtl8139_init_module () run the following code after insmod:

Static int _ init rtl8139_init_module (void)
{
Return pci_module_init (& rtl8139_pci_driver );
}

It calls pci_module_init () directly. The function code is in Linux/drivers/net/eepro100.c and the rtl8139_pci_driver is defined in our driver code, it is the link between the driver and the PCI device. Rtl8139_pci_driver is defined as follows:

Static struct pci_driver rtl8139_pci_driver = {
Name: MODNAME,
Id_table: rtl8139_pci_tbl,
Probe: rtl8139_init_one,
Remove: rtl8139_remove_one,
};

Pci_module_init () is not defined in the driver code. You must have thought that it is a standard interface provided by the Linux kernel to the module. What does this interface do, I have tracked this function. Pci_register_driver () is called. in Linux/drivers/pci. c, pci_register_driver does three things.

① The rtl8139_pci_driver parameter is registered in the kernel. There is a large linked list of PCI devices in the kernel. The PCI driver is mounted here.

② It is to view the configuration space of all PCI devices on the bus (NIC is a type of PCI device). If the identification information is the same as id_table in rtl8139_pci_driver, rtl8139_pci_tbl is defined as follows:

Static struct pci_device_id rtl8139_pci_tbl [] _ devinitdata = {
{0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 },
{PCI_ANY_ID, 0x8139, 0x10ec, 0x8139, 0 },
{0 ,}
};

The driver is used to drive the device, so the probe function in rtl8139_pci_driver is called rtl8139_init_one, which is defined in our driver, it is used to initialize the entire device and make some preparations. Note that pci_device_id is a structure defined by the kernel to identify different PCI devices. For example, 0x10ec here represents Realtek, we scanned the configuration space of the PCI device. If we found a device manufactured by Realtek, the two would be the same. Of course, after the company number, you have to check other device numbers and other devices. If they are all correct, it means that this driver can serve this device.

③ The rtl8139_pci_driver structure is mounted on the data structure (pci_dev) of the device, indicating that the device has its own driver. The driver also finds its service object.

PCI is a bus standard, and the devices on the PCI bus are PCI devices. These devices have many types, including Nic devices. Each PCI device is abstracted as a data structure in the kernel pci_dev, it describes all the features of a PCI device. For more information, see related documents. However, there are several areas that have a very large relationship with the driver, which must be explained. PCI devices comply with the PCI standard. All PCI devices in this section are the same. Each PCI device has a register storing the configuration space. The format is the same, for example, the first register is always the manufacturer's number. For example, Realtek is the 10ec, while Intel is the other number. These are all numbers applied by merchants like standard organizations. They must be different. I can identify the manufacturer and device number by configuring the space. No matter what platform, x86, or ppc, they are all in the same standard format. Of course, the uniform format of these PCI configuration spaces is not enough. For example, humans all have noses and eyes, but not all have the same length of noses and eyes. The NIC device is a PCI device and must comply with the rules. The PCI configuration space is integrated into the device, but it is a NIC and must be integrated with a register that can control the NIC. Register access becomes a problem. In Linux, we map these registers to the primary memory virtual space. In other words, our CPU memory access command can access these control registers in the peripherals. To sum up, there are two types of PCI devices. One is the configuration space, which is the unified format of the operating system or BIOS control peripherals. CPU commands cannot be accessed, to access this space, you need to use the BIOS function. In fact, the Linux function to access the configuration space drives the BIOS to complete read/write access through CPU commands. The other type is the general control register space. After this part is mapped, the CPU can be accessed to control the operation of the device.

Now let's go back to the second step of pci_register_driver above. If we find the opposite number between the relevant device and our pci_device_id structure array, it means we have found the service object, then call rtl8139_init_one, it mainly does seven things:

① Create a net_device structure so that it represents the network device in the kernel. However, the reader may ask, pci_dev also represents this device. What is the difference between the two? As we have discussed above, Nic devices must comply with PCI specifications, it is also responsible for its role as a NIC device, so it is divided into two parts, pci_dev is used to be responsible for the PCI specification of the NIC, here, net_device is responsible for the network device of the network card.

Dev = init_etherdev (NULL, sizeof (* tp ));
If (dev = NULL ){
Printk ("unable to alloc new ethernet \ n ");
Return-ENOMEM;
}
Tp = dev-> priv;

In Linux/drivers/net/net_init.c, The init_etherdev function allocates net_device memory and performs initial initialization. It is worth noting that a member of net_device, priv, represents private data of different NICs. For example, Intel nic and Realtek NIC are represented by net_device in the kernel. However, they are different. For example, Intel and Realtek use different methods to implement the same function, which are reflected by priv. So here we will compare it with net_device. When memory is allocated, all the members except priv in net_device are fixed, and the size of priv can be arbitrary. Therefore, the size of priv should be passed during allocation.

② Enable this device (in fact, the device register ing function is enabled)

Rc = pci_enable_device (pdev );
If (rc)
Goto err_out;
Pci_enable_device is also an interface developed by the kernel. The code is in drivers/pci. in c, the author traces and finds that this function is mainly used to set the 0-bit and 1-position of the Command domain in the PCI configuration space to 1, so as to enable the device, because the official datasheet of rtl8139 shows that the two functions are to enable memory ing and I/O ing. If not, the function of ing the control register space to the memory space discussed above is blocked, which is very unfavorable to us. In addition, pci_enable_device has also enabled some interruptions.

③ Obtain various resources

Mmio_start = pci_resource_start (pdev, 1 );
Mmio_end = pci_resource_end (pdev, 1 );
Mmio_flags = pci_resource_flags (pdev, 1 );
Mmio_len = pci_resource_len (pdev, 1 );

[1] [2] [3] [4] Next page

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.