linux Pci character-driven basic loading process

Today a friend asked me linux system Pci character-driven loading process, simply order a bit, the way to make a record.

First, that header files need to include:
a complete character drive generally contains the following headers:

#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/fcntl.h>
#include <linux/cdev.h>
#include <linux/version.h>
#include <linux/vmalloc.h>
#include <linux/ctype.h>
#include <linux/pagemap.h>
#include <linux/module.h>
#include <linux/ioctl.h>
#include <linux/io.h>
#include <linux/dma-mapping.h>
#include <linux/pci.h>
#include <linux/device.h>

Of course, you can increase the header file based on actual usage.

First, there must be a function of:
module_init (Pci_init_module);
module initialization function, this function is called when a drive is mounted;

static int Pci_init_module (void);
This function requires developers to realize their own, specific implementation requires a combination of business needs. This function is called by the module initialization function;

module_exit (Pci_cleanupmodule);
call this function when the function is driven unloaded, unload instruction input;

static void Pci_cleanupmodule (void);
This function requires developers to realize their own, to free the memory allocated to a process-driven execution. This function is called by the uninstall module function;

MODULE_AUTHOR ();
developer name registration function (can be a drive name can also be a developer name);

MODULE_LICENSE ( "GPL"); open protocol drivers employed, typically using default "GPL" to facilitate dynamic drive is mounted.

The following functions will be used in a real drive:
static int __init pci_probe (struct pci_dev dev *, const struct * pci_device_id the above mentioned id);
drive detection function for detecting whether the current device information stored in a matching device, after a successful match you can access the device;

static int Pci_open (struct inode * inode , struct file * filp);
This function is called by the user-level software, when a driver opens the open function, the function will be called. This function returns out device descriptor from the device tree stored into the own device descriptor, will be used in subsequent operations;

static int Pci_release (struct inode * inode , struct file * filp);
This function is called by the user-level software, when the close function using the drive, this function will be called. General details of this function need not be implemented directly "return 0;" to;

static ssize_t Pci_read (struct file * filp , char __user * buf, size_t count, loff_t * f_pos);
This function is called by the user-level software, data used when reading apparatus read function will call this function;

static ssize_t Pci_write (struct file * filp , const char __user * buf, size_t count, loff_t * f_pos);
This function is called by the user-level software, when a write function writes data to the device, will call this function;

int Pci_ioctl static (/ * struct the inode the inode, / * struct the filp File, unsigned int cmd, unsigned Long Arg);
This function is called by the user-level software, the device for operating a virtual memory space (physical address by the device when using the ioctl function mapped into the virtual address space of the system, from bar0 to six bar5 space, an actual device typically achieved two or three spaces, which can be used as bar0 io or memory space, of the BAR1 bar5 generally to memory space);
special note: this End the overall function is in the kernel 2.6.11 or later and realize, in the 3.2.5 kernel (except ... I do not remember specifically) and above need to comment inode parameters, with the actual use of the process is less than this parameter (in Pci_open function has been achieved saving device descriptor);

static loff_t Pci_llseek (struct file * filp , loff_t off, int whence);
This function is called by the user-level software, when a seek function data driver jumps are positioned;

static int scan_bars (struct pcie_dma_bookkeep * bk_ptr , struct pci_dev * dev);
generally used to print bar0 bar5 related description information, such bar0 start address and end address;

static int __init map_bars (struct pcie_dma_bookkeep * bk_ptr, struct pci_dev * dev);
the device are mapped to the physical address of the kernel virtual memory implementation and related description information, such as the start address and the end address mapping bar0 the like;

static void unmap_bars (struct pcie_dma_bookkeep * bk_ptr , struct pci_dev * dev);
recovering bar memory mapping, and initializes bar structure.

Here are some real driver associated structure used:
static struct = {the file_operations demo_fops
.owner = THIS_MODULE,
.Open = Pci_open,
.release = Pci_release,
};
device structure callback function, wherein the three must be filled when the drive mount after a successful, when (such as open function) user-space call the relevant function, will be found to perform the binding function of Pci_open by the structure object that operational processes are: a file handle to traverse in the device tree and find a match file handle, and then the acquired device descriptor currently driven, related operations (where abstraction is used, the system provides the specific function by the device descriptor format, to achieve these functions is implemented by the above stresses themselves, but the system responsible for calling these functions);

struct pci_device_id pci_ids static [] = {
{PCI_DEVICE (MANF_ID, MODEL_CODE)},
{0}
};
device identification structure, MANF_ID this is a vendor ID, MODEL_CODE product ID, which are provided by the equipment manufacturers;

pci_driver driver_ops = struct {static
.name = AMC4401ADEVNAME,
.id_table = pci_ids,
.PROBE = pci_probe,
.remove = pci_remove,
};
apparatus detection structure, if the driver intends to register in the device tree needs to be implemented after the detection device device descriptor will join in the device tree.

Drive in the computer sense:
the original intention to achieve the computer system is to facilitate the management, efficient access to the device. The drive to achieve is to allow the system to avoid the cumbersome, repetitive meaningless work.
The computer system provides a unified drive to write structure, not only eliminates the need for duplicate driver framework written (such as character driven only need to write a complete code can be reused), but also by the high efficiency, does not need to a drive to rewrite the kernel file;
the device tree like our program execution, drive execution of the program can be seen as one of the library (file library metaphor because the system does not need to know how to drive to achieve, it only needs to know the information that is relevant can, of course, poorly designed driver can also cause system crashes and other issues);

In front of so many long-winded for a foundation below, the following description of a character driven to perform basic process:

First enter the initialization function:
1. Allocate a device object (device configuration generally be prepared according to the request);
2. Registration pci device structure of the object passing the detection device;

After successful registration pci apparatus, enters the detection function:
1. Set the device private data;
2. custom device name registration device number (device number generated by the system, may be manually set the device number register);
3. Create class (device use driver management, copy information to the device / path under dev);
4. binding device descriptor and the initialization apparatus callback structure objects;
5. binding device descriptor device number;
6. the detection apparatus is valid (if not detected matching device, no longer run);
7. detecting device requesting information (comparing the current from the device name and device name for a device descriptor are the same);
8. set device to work in a bus master mode;
9. Analyzing msi is valid (effective capacity expressed hardware interrupt);
10 bar obtaining information (address bar0 to the bar5);
11. memory mapped into virtual memory bar;
12. dma configuration settings (if present dma);

Usually these steps, a driving basic loaded, the remaining operation is the application layer.

Published 87 original articles · won praise 195 · views 170 000 +

Guess you like

Origin blog.csdn.net/a29562268/article/details/84778768