目录
一、引言
二、PCI总线介绍
三、PCI设备驱动组成
四、查看本机上的PCI设备
一、引言
PCI总线在linux中应用的十分广泛,本文就来简单介绍一下
二、PCI总线描述
1、PCI总线结构
PCI是CPU和外围设备通信的高速传输总线。普通PCI总线带宽一般为132MB/s(在32bit/33Mhz下)或者264MB/s(在32bit/66Mhz下)。
PCI总线体系结构是一种层次式的体系结构,PCI桥设备占据着重要的地位,它将父总线与子总线连接在一起,从而使整个系统看起来像一颗倒置的树形结构。
PCI桥包括以下几种:
Host/PCI桥:用于连接CPU与PCI根总线,在PC中,内存控制器也通常被集成到Host/PCI桥设备芯片,Host/PCI桥通常被称 为“北桥芯片组”。
PCI/ISA桥:用于连接旧的ISA总线。PCI/ISA桥也被称为“南桥芯片组”。
PCI-to-PCI桥:用于连接PCI主总线与次总线。
2、PCI配置空间访问
PCI有3种地址空间:PCI/IO空间、PCI内存地址空间和PCI配置空间。
1、PCI配置空间(共为256字节):
制造商标识:由PCI组织分配给厂家。
设备标识:按产品分类给本卡编号。
分类码:本卡功能分类码。
申请存储器空间:PCI卡内有存储器或以存储器编址的寄存器和I/O空间,为使驱动程序和应用程序能访问它们。配置空间的基地址寄存器用于此目的。
申请I/O空间:配置空间基地址寄存器用来进行系统I/O空间申请。
中断资源申请:向系统申请中断资源。
内核为驱动提供的函数访问配置空间:
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);
2、PCI的I/O和内存空间:
获取I/O或内存资源:
pci_resource_start(struct pci_dev *dev, int bar);/*Bar值的范围为0-5*/
该函数返回六个 PCI I/O 区域之一的第一个地址(内存地址或 I/O 端口编号)。
pci_resource_end(struct pci_dev *dev, int bar) /* Bar值的范围为0-5*/
该函数返回第 bar 个 I/O 区域的后一个地址。注意这是最后一个可用的地址,而不是该区域之后的第一个地址。
pci_resource_flags(struct pci_dev *dev, int bar) /* Bar值的范围为0-5 */
该函数返回资源关联的标志。资源标志用来定义单个资源的某些特性。对与 PCI I/O 区域关联的 PCI 资源,该信息从基地址寄存器中获得,但对其它与 PCI 设备无关的资源,它可能来自任何地方。所有的资源标志定义在 <linux/ioport.h> 中,下面列出其中最重要的几个:
IORESOURCE_IO
IORESOURCE_MEM
如果对应的 I/O 区域存在,将设置上面标志中的一个,而且只有一个。
IORESOURCE_PREFETCH
IORESOURCE_READONLY
上述标志定义内存区域是可预取的,或者是写保护的。对 PCI 资源来讲,从来不会设置后面的那个标志。通过使用 pci_resource_flags函数,设备驱动程序可完全忽略底层的 PCI 寄存器,因为系统已经使用这些寄存器构建了资源信息。
3、PCI设备相关使用接口
1、申请/释放I/O或内存资源:
int pci_request_regions(struct pci_dev *pdev, const char *res_name);void pci_release_regions(struct pci_dev *pdev);
2、获取/设置驱动私有数据:
void *pci_get_drvdata(struct pci_dev *pdev);void pci_set_drvdata((struct pci_dev *pdev, void *data);
3、使能/禁止PCI设备:
int pci_enable_device(struct pci_dev *pdev);int pci_disable_device(struct pci_dev *pdev);
4、使能/禁止PCI设备:
int pci_enable_device(struct pci_dev *pdev);int pci_disable_device(struct pci_dev *pdev);
5、设置主总线为DMA模式:
void pci_set_master(struct pci_dev *pdev);
三、PCI设备驱动组成
PCI本质上就是一种总线,具体的PCI设备可以是字符设备、网络设备、USB等,所以PCI设备驱动应该包含两部分:
1、PCI驱动
2、根据需求的设备驱动
所以PCI设备一般都具有双重身份,一方面作为PCI设备注册到Linux内核,另一方面,作为字符设备或者块设备,或者网络设备注册到Linux内核,在看PCI设备时一定要注意到这点。
一般如果某个外设是PCI接口的,就需要应用内核的PCI驱动框架,与USB等总线相类似
内核中PCI驱动框架的相关实现函数位于’/kernel/drivers/pci/'下
根据需求的设备驱动是最终目的,PCI驱动只是手段帮助需求设备驱动达到最终目的而已。换句话说PCI设备驱动不仅要实现PCI驱动还要实现根据需求的设备驱动。
PCI设备驱动初始化
1、初始化PCI设备结构体 intel 82599 万兆网卡
pci 设备的编码如下:
2、注册PCI设备到内核 pci_register_driver
3、激活PCI设备 pci_enable_device_mem()
一般情况下,在pci设备的probe函数中,在驱动程序可以访问pci设备的任何设备资源之前,驱动程序必须调用pci_enable_device_mem()函数。
4、PCI设备申请存储资源 pci_request_selected_regions
5、申请成总线主DMA模式 pci_set_master,文件同上
6、一般情况下,都是在设备驱动的Probe函数中,完成PCI设备驱动的初始化,以及作为字符设备,块设备,或者网络设备的注册与初始化功能。
四、查看本机上的PCI设备
lspci 显示设备上的pci设备
显示设备上pci设备的pci号