<背景>

PCI设备有许多地址配置的寄存器,初始化时这寄存器来配置设备的总线地址,配置好后CPU就可以访问该设备的各项资源了。(提炼:配置总线地址)
 
<配置寄存器>
 
(1)256字节的PCI配置空间分为64字节的头标区和192字节的设备相关区两部分。头标区的各个寄存器用来唯一地识别设备;设备相关区则保存一些与设备相关的数据。
(2)配置空间的头标区又分为两部分:前16个字节的定义在各种类型的PCI设备中都是一样的;剩余的字节随设备类型不同而有所不同。位于偏移地址0EH处的头标类型字段规定了头标区的布局结构。目前,规范定义了三种头标类型。
                                 
a:设备的识别
(1)  供应商代码:该寄存器用于识别PCI设备的制造商,具体代码由PCI SIG(http://www.pcisig.com)分配。0FFFFH是无效的供应商代码。
(2)       设备代码。该寄存器用来标识某供应商生产的具体设备,代码由各供应商定义。供应商代码和设备代码,读者可以到网站http://www.pcidatabase.com/查阅。
(3)       版本号。该寄存器用来定义指定设备的版本信息。
(4)       头标类型。该字段的第7位为“1”标识该设备是多功能设备,为“0”标识为单功能设备;该字段的0~6位就是上文表中所述的头标类型。
(5)       设备分类代码。用来标识设备的总体功能和特定的寄存器级编程接口。
上面5个字段均为只读类型,所有的PCI设备都必须实现其功能。
b:设备控制和设备状态
(1)       命令寄存器为一个设备发出和响应PCI总线命令提供粗略的控制。图4就是命令寄存器格式。
 
位0(I/O空间控制):控制对I/O空间访问的响应。该位为0时,禁止设备响应对I/O空间的访问;该位为1时,允许设备响应I/O空间的访问。缺省设置为0。
位1(存储器空间控制):控制一个设备对存储器空间访问的响应。该位为0时,禁止响应;该位为1时,允许设备响应对存储器空间的访问。缺省设置为0。
 
状态寄存器用来记录PCI总线有关的状态信息。
c:基址寄存器
PCI设备中,除了配置空间外,还有两个物理空间:内存空间和I/O空间。为了访问这两个地址空间,就必须使用基址寄存器。头标类型0中涉及3种基址寄存器:内存空间基址寄存器、I/O空间基址寄存器和扩展ROM基址寄存器。
d:其他寄存器
其他寄存器包括一些本文不涉及到的寄存器,如中断引脚、中断线等等。 
<PCI配置空间的访问>
    a:PCI规范使用从0CF8H~0CFFH 这8个I/O地址来访问所有设备的PCI配置空间。这8个字节实际上构成了两个32位寄存器:0CF8H寄存器叫做“配置地址寄存器”;0CFCH叫做“配置数据寄存器”。当要访问配置空间的寄存器时,先向地址寄存器写上目标地址,然后就可以从数据寄存器中读写数据了。
        PCI配置空间对应于一个PCI逻辑设备,所以要访问一个配置空间的某个寄存器,必须要指定:PCI总线号、PCI设备号、PCI设备功能号和寄存器号。配置地址寄存器的格式如下:
                     
       第0、1位上的“0”是用来要求你只能按双字(4字节)来读写配置空间寄存器。第31位“使能位”用来决定是否允许访问配置空间:为“1”时表示可以访问;为“0”时表示不可以访问。
        从上面的配置地址寄存器的格式我们可以看出:总线号从0~255、设备号从0~31、功能号从0~7。根据配置空间的第0个寄存器是否返回0FFFFH值来判断是否存在该PCI设备(这里可以看出PCI为什支持32个设备)
 
<PCI驱动开发概总>
对于驱动开发人员来说,pci具有如下吸引人的优势:
a:设备自动配置系统,与旧的ISA驱动程序不一样,pci驱动不需要实现复杂的检测逻辑。
b:系统启动时,BIOS(如果是嵌入式系统内核本身会完成该任务)会遍历pci总线并分配资源(比如中断优先级,I/O基地址) 
c: 设备去驱动程序会查询叫做"PCI配置空间"的内存来找到资源分配情况
d:PCI设备总共具有256B的配置空间内存。配置空间 顶部64B空间的含义是标准的,所有设备的配置在这段区域都是相似的。该空间被分成状态,I/O基地址,中断线。
 
<访问PCI>
a:内核函数
pci_read_config_[byte|word|dword](struct pci_dev *pdev,int offset,int *value)
pci_write_config_[byte|word|dword](struct pci_dev *pdev,int offset,int *value)
形参分析:
pdev:指向PCI设备的结构体
offset:配置空间的偏移地址
value:需要写入或读出数据的存放位置
举例:
unsigned char irq;
pci_read_config_byte(pdev,PCI_INTERRUPT_LINE,&irq);
注意:在配置空间中的中断号的偏移是60,这为什么不使用60,是因为在Linux内核中/include/linux/pci_regs.h进行了定义。
 
<I/O和内存>
I/O访问
a:要访问一个PCI设备的I/O空间或内存空间在内存或I/O区域的映射。需要读取配置空间的相应基地址寄存器里得到I/O区域的基地址。
(1)从配置区域相应基址寄存器得到I/O区域的基地址
unsigned long io_base = pci_resource_start(pdev,bar)
注意:该函数还有相应的变形
unsigned long pci_resource_[start|lenght|flags](struct pci_dev*pdev, int bar)
(2)调用内核函数request_region()获得这个IO区域,标明这片区域对应的设备
request_region(io_base,length,"mydriver")
(3)这样就可以使用I/O操作函数访问这些寄存器了,
inl();
outl();

 内存访问
(1)调用该函数获得内存基地址
unsigned long pci_resource_[start|lenght|flags](struct pci_dev*pdev, int bar)
(2)调用内核函数request_mem_region()获得这个内存区域,标明这片区域对应的设备
request_region(mmio_base,mmio_length,"mydriver")
(3)将获得内存地址转换成虚拟地址
buffer = pci_iomap(pdev, bar,mmio_length)
 
<驱动实例>
a当PCI热插拔检测到新插入的设备的ID属性和驱动程序中的pci_device_id表里的ID信息一致的时候。该层将激发该驱动程序的probe()函数被调用。进一步注册相应的设备驱动。可以看出首先得要注册pci_driver程序:
调用函数pci_register_drivet()
b:

Linux驱动之PCI的更多相关文章

  1. linux驱动---用I/O命令访问PCI总线设备配置空间

    PCI总线推出以来,以其独有的特性受到众多厂商的青睐,已经成为计算机扩展总线的主流.目前,国内的许多技术人员已经具备开发PCI总线接口设备的能 力.但是PCI总线的编程技术,也就是对PCI总线设备的操 ...

  2. 【Linux开发】【DSP开发】Linux设备驱动之——PCI 总线

    PCI总线概述  随着通用处理器和嵌入式技术的迅猛发展,越来越多的电子设备需要由处理器控制.目前大多数CPU和外部设备都会提供PCI总线的接口,PCI总线已成为计算机系统中一种应用广泛.通用的总线标准 ...

  3. linux 注册一个 PCI 驱动

    为了被正确注册到内核, 所有的 PCI 驱动必须创建的主结构是 struct pci_driver 结构. 这个结构包含许多函数回调和变量, 来描述 PCI 驱动给 PCI 核心. 这里是这个结构的一 ...

  4. 嵌入式Linux驱动开发日记

    嵌入式Linux驱动开发日记 主机硬件环境 开发机:虚拟机Ubuntu12.04 内存: 1G 硬盘:80GB 目标板硬件环境 CPU: SP5V210 (开发板:QT210) SDRAM: 512M ...

  5. zynq linux驱动之PL-PS中断【转】

    转自:https://blog.csdn.net/h244259402/article/details/83993524 PC:Windows 10 虚拟机:ubuntu 16.04 vivado:2 ...

  6. Linux 驱动开发

    linux驱动开发总结(一) 基础性总结 1, linux驱动一般分为3大类: * 字符设备 * 块设备 * 网络设备 2, 开发环境构建: * 交叉工具链构建 * NFS和tftp服务器安装 3, ...

  7. linux驱动工程面试必问知识点

    linux内核原理面试必问(由易到难) 简单型 1:linux中内核空间及用户空间的区别?用户空间与内核通信方式有哪些? 2:linux中内存划分及如何使用?虚拟地址及物理地址的概念及彼此之间的转化, ...

  8. Linux驱动开发必看详解神秘内核(完全转载)

    Linux驱动开发必看详解神秘内核 完全转载-链接:http://blog.chinaunix.net/uid-21356596-id-1827434.html   IT168 技术文档]在开始步入L ...

  9. linux驱动之一语点破天机

    <const 关键字> 在嵌入式系开发中,const关键字就是“只读”的意思   <为什么要ARM需要进行C语言环境的初始化> 在汇编情况下,指令的跳转,保护现场需要保存的数据 ...

随机推荐

  1. HDU 2063 过山车 二分匹配

    解题报告:有m个女生和n个男生要结成伴坐过山车,每个女生都有几个自己想选择的男生,然后要你确定最多能组成多少对组合. 最裸的一个二分匹配,这是我第一次写二分匹配,给我最大的感受就是看那些人讲的匈牙利算 ...

  2. GDB基本用法

    基本命令 进入GDB:#gdb test test是要调试的程序,由gcc test.c -g -o test生成.进入后提示符变为(gdb) . 查看源码:(gdb) l 源码会进行行号提示. 如果 ...

  3. Anaconda+django写出第一个web app(一)

    在安装好Anaconda和django之后,我们就可以开始创建自己的第一个Web app,那么首先创建一个空文件夹,之后创建的文件都在这个文件夹内. 启动命令行进入此文件夹内,可以先通过如下命令查看一 ...

  4. CF448C Painting Fence

    传送门 Descriptionzed 最近总是受到 Farmer 的困扰,因此他在自家的门前插了一排栅栏以防农气的入侵.栅栏由 N 个竖条栅栏横向组成,每个竖条栅栏宽度为 1.过了一段时间,zed 觉 ...

  5. Django进阶(路由系统、中间件、缓存、Cookie和Session、Ajax发送数据

    路由系统 1.每个路由规则对应一个view中的函数 url(r'^index/(\d*)', views.index), url(r'^manage/(?P<name>\w*)/(?P&l ...

  6. Linux日志文件/var/log详解

    更多内容推荐微信公众号,欢迎关注: 如果愿意在Linux环境方面花费些时间,首先就应该知道日志文件的所在位置以及它们包含的内容.在系统运行正常的情况下学习了解这些不同的日志文件有助于你在遇到紧急情况时 ...

  7. python 面试题4

    Python面试题 基础篇 分类: Python2014-08-08 13:15 2071人阅读 评论(0) 收藏 举报 最近,整理了一些python常见的面试题目,语言是一种工具,但是多角度的了解工 ...

  8. Python Challenge 第 5 关攻略:peak

    # -*- coding: utf-8 -*- # @Time : 2018/9/26 14:03 # @Author : cxa # @File : pickledemo.py # @Softwar ...

  9. 公司xenserver搭建的使用

    [root@xenserver ~]# ls -l /dev/disk/by-path/total 0lrwxrwxrwx 1 root root  9 Jan 19 16:33 pci-0000:0 ...

  10. Mac ssh

    mac的终端默认在打开一个新的tab/window的时候需要重新输入ssh的密码, 很不方便.本文完成在mac中设置,实现secureCRT/xshell里的克隆会话功能, 即新开一个terminal ...