Linux子系统系列-PCI

趁这几天有空,将PCI这块的东西也简单整理一下。关于PCI,fudan_abc大侠的“PCI那些事儿”是最佳的,这里简单根据一些工作笔记做些整理,点一下大致框架,以作备忘。

0,背景

1,PCI driver结构

2,PCI driver实现

3,关于PCI core

------------------------------------------------------------------------------

0,背景

PCI,十多年前就有的一个总线标准,历久弥新,生命力旺盛。虽然现在基于PCI有了很多派生,但符合PCI标准的设备还是随处可见。其原因琢磨着可能有两个:PCI总线标准极大的降低了硬件设备驱动的编写难度和繁琐度;Linux驱动模型对PCI设备驱动的抽象更进一步降低了PCI驱动的难度。设计时除了单独的商业目的多考虑一下终端使用者或开发人员,市场一定会给你丰厚的回报,:)

在分析或编写PCI driver之前一定要了解一下PCI系统在计算机中的全貌,下面大部引自fudan_abc的文章:

PCI的结构中会涉及到bridge的概念,所谓桥,是用来将多个PCI总线,或PCI总线于ISA等其他总线连接起来的东西。各种桥里面比较特殊的一个是Host bridge,它连接的是CPU和PCI总线0,它集成在我们常说的北桥中(北桥和南桥并称芯片组,芯片组里距离CPU最近的就是北桥)。明白了Host Bridge,再来看看PCI bus0,也就是primary PCI bus,主PCI总线,可能还会有PCI bus1,PCI bus2,但PCI bus0是一定存在的。一个系统可以拥有多个PCI总线,这多个PCI总线之间的连接要靠另外一种桥,PCI-PCI桥。通过了PCI-PCI桥,整个PCI系统就构成了一个层次的、树状地结构,这些树就像HUB同是USB设备一样,PCI-PCI桥等各种各样的桥也都是PCI设备。每个PCI总线上可以支持32个PCI设备,每个设备又可以支持8种功能,这里所谓的设备一般指那种PCI总线上的具体卡/设备/芯片,每块PCI卡上可以有若干个功能模块,它们共用了同一个PCI卡,从逻辑的角度来说,每个功能模块都是一个逻辑设备。

明白了PCI系统的结构,总线枚举的概念又来了:

按照规范,每个PCI设备都有那么一张表,就是所谓的配置寄存器,相应的驱动编写都要依赖这种表。这个表中的一部分内容都固化在了PCI设备的芯片里面,获取的就要去访问PCI设备。但系统一开始只有那条PCI bus0能够访问,其他的PCI总线和设备一切都还是未知, 要把这些未知变为已知,这就需要总线枚举。系统引导时,对于PCI子系统来说,会首先有个总线枚举的阶段,从PCI bus0开始扫描,遇到一个设备是PCI-PCI桥,就指定一个新的总线号,比如1,这样PCI bus1就有了,也就可以继续扫描了,如果遇到一个其他PCI设备,就将它记录下来,直到将所有的PCI-PCI桥和PCI设备给晾出来,组成系统的PCI树。

1,PCI driver结构

PCI设备的驱动一般分为两层,最下一层是linux的PCI core子系统,上层是根据具体芯片实现的一些操作。

2,PCI driver的实现

一个完整的PCI driver要完成以下工作:

1)定义一个这个驱动可以支持的设备的表

static const struct pci_device_id cmd64x_pci_tbl[] = {
    { PCI_VDEVICE(CMD, PCI_DEVICE_ID_CMD_643), 0 },
    { PCI_VDEVICE(CMD, PCI_DEVICE_ID_CMD_646), 1 },
    { PCI_VDEVICE(CMD, PCI_DEVICE_ID_CMD_648), 2 },
    { PCI_VDEVICE(CMD, PCI_DEVICE_ID_CMD_649), 3 },
    { 0, },
};

2)在编译时,driver将会使用MODULE_DEVICE_TABLE宏将这个list传递给build system(不是kernel)

我们在make module_install时,这个表的内容会被转译成module的一个数据库的内容,被安装在用户侧。

当系统发现一个新的PCI设备时,PCI core 会向kernel发出一个通知,kernel接着会将这个通知转向用户层这类通知的监听程序(udev)通过uevents机制。udev会从uevent中解析出这个通知的设备信息并调用modprobe。紧接着,modprobe会基于这些信息分析modules.alias,安装相应的模块。

3)使用PCI core的API:pci_register_device()注册设备信息。

4)PCI core会根据注册的设备信息来扫描是否有匹配的驱动,若发现,PCI core会调用probe函数来让driver获取PCI设备的控制权。

 

3,关于PCI core

linux的工程师们将PCI相关的一些与平台/芯片无关的一些操作抽象出来,形成这个PCI core子系统。这个子系统除了提供一些PCI相关的API之外,还可以方便快捷的将driver以符合linux设备模型规范的方式注册到kernel。

无需多说,用过的都说好:

1)保持尽量一致的对外接口,增加你的驱动的可移植性。

2)通过/sysfs提供一些常用接口到用户侧,方便管理调试。

3)让udev可以自动为PCI设备创建/dev目录下的节点并load需要的module。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值