Linux上PCI—E驱动设计

2016-09-26 21:37林齐梅
卷宗 2016年7期
关键词:驱动

摘 要:当前基于Linux内核的操作系统应用越来越广泛,开发基于Linux的设备驱动程序,具有很强的实用性和可移植性。本文简单介绍linux系统上PCI-E设备驱动的框架以及重要的数据结构。

关键词:Linux;PCI-E;PCI;驱动

Abstract:At present,the operating system based on Linux kernel is used more and more widely. It is very practical and portable to develop the device driver based on Linux. This article briefly introduces the framework and the important data structure of PCI-E device driver on Linux system .

Key word: Linux;PCI-E;PCI;Driver

PCI-Express 简称PCI-E,是一种完全不同于PCI、具有高速串行点对点双通道高带宽传输模式的全新总线规范,所连接的设备分配独享通道带宽,不共享总线带宽,支持端对端的可靠性传输。PCI-E在软件层面上兼容的PCI技术和设备,支持PCI设备和内存模组的初始化,也就是说驱动程序、操作系统完全兼容。

1 PCI设备与驱动关系

PCI设备通常由一组参数唯一地标识,它们被vendorID,deviceID和class nodes所标识,即设备厂商,型号等,这些参数保存在 pci_device_id结构中。每个PCI设备都会被分配一个pci_dev变量。所有的PCI驱动程序都必须定义一个pci_driver结构变量,在该变量中包含了这个PCI驱动程序所提供的不同功能的函数,同时,在这个结构中也包含了一个device_driver结构,这个结构定义了PCI子系统与PCI设备之间的接口。在注册PCI驱动程序时,这个结构将被初始化,同时这个 pci_driver变量会被链接到pci_bus_type中的驱动链上去。在pci_driver中有一个成员struct pci_device_id *id_table,它列出了这个设备驱动程序所能够处理的所有PCI设备的ID值。

2 基本框架

在用模块方式实现PCI设备驱动程序时,通常至少要实现以下几个部分:初始化设备模块、设备打开模块、数据读写和控制模块、中断处理模块、设备释放模块、设备卸载模块。下面给出一个典型的PCI设备驱动程序的基本框架,从中不难体会到这几个关键模块是如何组织起来的。

staticstruct pci_device_id example_pci_tbl [] __initdata ={

{PCI_VENDOR_ID_EXAMPLE,PCI_DEVICE_ID_EXAMPLE,PCI_ANY_ID,

PCI_ANY_ID,0,0, EXAMPLE},

{0,}};

struct example_pci {/* 對特定PCI设备进行描述的数据结构 */

unsigned int magic;

struct example_pci *next;/* 使用链表保存所有同类的PCI设备 */

/* ... */}

staticvoid example_interrupt(int irq,void*dev_id,struct pt_regs *regs){/* 中断处理模块 */

/* ... */}

staticstruct file_operations example_fops ={ /* 设备文件操作接口 */

owner: THIS_MODULE,/* demo_fops所属的设备模块 */

read: example_read,/* 读设备操作*/

write: example_write,/* 写设备操作*/

ioctl: example_ioctl,/* 控制设备操作*/

open: example_open,/* 打开设备操作*/

elease: example_release /* 释放设备操作*/

/* ... */};

staticstruct pci_driver example_pci_driver ={/ * 设备模块信息 */

name: example_MODULE_NAME,/* 设备模块名称 */

id_table: example_pci_tbl,/* 能够驱动的设备列表 */

probe: example_probe,/* 查找并初始化设备 */

remove: example_remove /* 卸载设备模块 */

/* ... */};

staticint __init example_init_module (void){

/* ... */}

staticvoid __exit example_cleanup_module (void){

pci_unregister_driver(&demo_pci_driver);

}

module_init( example_init_module);/* 加载驱动程序模块入口 */

module_exit( example_cleanup_module);/* 卸载驱动程序模块入口 */

3 主要数据结构

上面这段代码给出了一个典型的PCI设备驱动程序的框架,是一种相对固定的模式。主要用了几个重要的数据结构。

struct pci_device_id {

__u32 vendor, device;/* Vendor and device ID or PCI_ANY_ID*/

__u32 subvendor, subdevice;/* Subsystem ID's or PCI_ANY_ID */

__u32 class, class_mask;/* (class,subclass,prog-if) triplet */

kernel_ulong_t driver_data;/* Data private to the driver */

};

vendorID:标识硬件制造商,是一个16位的寄存器。

deviceID:设备ID,由制造商选择,也是一个16位的寄存器。

class:每个外部设备属于某个类(class),也是一个16位的寄存器。

struct pci_driver {

struct list_head node;

char*name;

conststruct pci_device_id *id_table;/* must be non-NULL for probe to be called */

int(*probe)(struct pci_dev *dev,conststruct pci_device_id *id);/* New device inserted */

void(*remove)(struct pci_dev *dev);/* Device removed */

/* ... */};

struct pci_driver它的作用并不仅仅是识别设备的id_table结构,还包括了检测设备的函数probe()和卸载设备的函数remove(),

struct pci_dev {

struct list_head bus_list;/* node in per-bus list */

struct pci_bus *bus;/* bus this device is on */

struct pci_bus *subordinate;/* bus this device bridges to */

void*sysdata;/* hook for sys-specific extension */

struct proc_dir_entry *procent;/* device entry in /proc/bus/pci */

struct pci_slot *slot;/* Physical slot this device is in */

unsignedint devfn;/* encoded device & function index */

unsignedshort vendor;

unsignedshort device;

/* ... */};

它詳细描述了一个PCI设备几乎所有的硬件信息,包括厂商ID、设备ID、各种资源等。

4 结束语

Linux PCI设备驱动实际包括Linux PCI设备驱动和具体设备本身驱动两部分,Linux PCI驱动是内核自带的,而我们需要完成的就是设备本身的驱动,比如本人做的超声数据采集卡的驱动。

参考文献

[1]:(美)博韦深入理解Linux内核[M],中国电力出版社,第三版。

[2]:(美)科波,LINUX设备驱动程序(第3版)[M],中国电力出版社,第三版。

作者简介

林齐梅(1984-),男,广东汕头人,学士学位,研究方向:超声探伤仪设备研发。

猜你喜欢
驱动
基于模糊PI控制的驱动防滑仿真系统分析
屈宏斌:未来五年,双轮驱动,砥砺前行
轨旁ATC系统门控柜接收/驱动板改造
基于S3C6410的Wi-Fi驱动移植实现