PCI驱动开发学习笔记(一)

news/2024/11/15 2:01:08/
  • PCIE简介

         PCIe作为串行总线的一种,它的发展必然和另一种总线架构密不可分:并行总线。

        像PCIe接口的显卡、声卡、网卡,都属于功能设备,在PCIe规范中,我们统称为Endpoint(简称EP)。还有其他两类设备,  一个是Root Complex,简称RC,另一个是switch(或者PCI中称为bridge),RC是根设备,通过switch和下游设备(可以是EP也可以是switch)进行桥接,从而各个PCIe设备组成了一个PCIe设备网络,信息就以数据包(TLP、DLLP)的形式在网络中传递。

一、PCI设备编号

         PCI设备的ID号由总线号(BUS NUMBER)、设备号(DEVICE NUMBER)和功能号(FUNCTION NUMBER)组成。

         一条PCI总线的设备号由PCI设备的IDSEL信号与PCI总线地址线的连接关系确定,即每一个PCI插槽的总线号和设备号都是固定的,这是硬件工程师决定的。

         PCI功能号与PCI设备的具体设计相关。在一个PCI设备中最多有8个功能设备,而且每一个功能设备都有各自的PCI配置空间,而在绝大数PCI设备中只有一个功能设备。

lspci  --- 枚举PCI设备
         01:00.0 VGA compatible controller: NVIDIA Corporation GM107 [GeForce GTX 745] (rev a2)
        (bus number 0~0xff[2^8]):(device number 0~0x1f[2^5]).(function number 0~0x07[2^3])  Class:Vendor Device (revision)

二、PCI配置空间

每个PCI逻辑设备都有自己的配置空间,里面存储了一些基本信息,生产商,IRQ中断号,还有就是定义了mem空间和io空间的起始地址和大小。

HOST主桥使用寄存器号,访问PCI设备配置空间的某个寄存器。

三、PCI驱动函数接口

         1.  pci驱动注册

          pci_register_driver(struct pci_driver *drv)

          pci_unregister_driver(struct pci_driver *drv)

static struct pci_device_id vt8623_devices[] = {{PCI_DEVICE(PCI_VENDOR_ID_VIA, 0x3122)},{0, 0, 0, 0, 0, 0, 0}
};       
static struct pci_driver vt8623fb_pci_driver = {.name       = "vt8623fb",.id_table   = vt8623_devices,.probe      = vt8623_pci_probe,.remove     = vt8623_pci_remove,.suspend    = vt8623_pci_suspend,.resume     = vt8623_pci_resume,
};pci_register_driver(&vt8623fb_pci_driver);

          2. 激活PCI设备

                在驱动程序可以访问PCI设备的任何设备资源之前(I/O区域或者中断),驱动程序必须调用该函数:

     int pci_enable_device(struct pci_dev *dev);                       /*driver/pci/pci.c*/这个函数主要就是把PCI配置空间的Command域的0位和1 位置成了1,从而达到了开启设备的目的。

          3.  访问PCI配置空间

    int pci_read_config_byte(conststruct pci_dev *dev,int where, u8 *val);/*8位,读入一个字节*/int pci_read_config_word(conststruct pci_dev *dev,int where, u16 *val);/*16位,读入两个字节*/int pci_read_config_dword(conststruct pci_dev *dev,int where, u32 *val);/*32位,读入四个字节*/
    int pci_write_config_byte(conststruct pci_dev *dev,int where, u8 *val);/*8位,写入一个字节*/int pci_write_config_word(conststruct pci_dev *dev,int where, u16 *val);/*16位,写入两个字节*/int pci_write_config_dword(conststruct pci_dev *dev,int where, u32 *val);/*32位,写入四个字节*/

          4. 申请IO端口和内存资源

               通知内核该设备对应的IO端口和内存资源已经使用,其他的PCI设备不要再使用这个区域

             int  pci_request_regions(struct pci_dev *dev, const char *res_name)

             int  pci_release_regions(struct pci_dev *pdev)

             int  pci_request_mem_regions(struct pci_dev *pdev, const char *name)

             int  pci_release_mem_regions(struct pci_dev *pdev)

             int  pci_request_io_regions(struct pci_dev *pdev, const char *name)

             int  pci_release_io_regions(struct pci_dev *pdev)

 

           5. 访问PCI的I/O和内存空间

             int pci_resource_[start|end|flags|len](struct pci_dev *dev,  int bar)  //Bar值的范围为0-5

 在硬件加电初始化时,BIOS固件统一检查了所有的PCI设备,并统一为他们分配了一个和其他互不冲突的地址,让他们的驱动程序可以向这些地址映射他们的寄存器,这些地址被BIOS写进了各个设备的配置空间,因为这个活动是一个PCI的标准的活动,所以自然写到各个设备的配置空间里而不是他们风格各异的控制寄存器空间里。当操作系统初始化时,他为每个PCI设备分配了pci_dev结构,并且把BIOS获得的并写到了配置空间中的地址读出来写到了pci_dev中的resource字段中。这样以后我们在读这些地址就不需要在访问配置空间了,直接跟pci_dev要就可以了,我们这里的四个函数就是直接从pci_dev读出了相关数据。

Linux认为这个地址是IO地址,如果要访问的话可以通过ioremap映射到内核空间,然后通过readl/writel等IO接口进行操作。

           6.  私有数据

             pci_set_drvdata    设置驱动私有数据

             pci_get_drvdata    获取驱动私有数据

           7. 主设备模式

              pci_set_master    设定设备工作在总线主设备模式

 

 

 

 

 


http://www.ppmy.cn/news/274648.html

相关文章

Linux PCI总线驱动-1

Linux PCI总线驱动-1 一、PCI总线介绍1. PCI介绍2. PCI接口3. PCI-X介绍4. PCI-E介绍4.1 下图从上到下依次是PCIEX16,X1,X44.2 PCI-E各版本的传输速度4.3 PCI-E不同传输通道数设备的金手指数和长度4.4 三种接口的传输速度比较 二、pci设备基础知识2.1 内…

PCI驱动程序实现

1、数据结构: PCI设备上有三种地址空间:PCI的I/O空间、PCI的存储空间和PCI的配置空间。CPU可以访问PCI设备上的所有地址空间,其中I/O空间和存储空间提供给设备驱动程序使用,而配置空间则由Linux内核中的PCI初始化代码使用。内核在…

vxworks pci驱动解析

PCI驱动分为两种类别: 1.CPU通过io方式访问的PCI设备驱动 2.dma方式的PCI设备驱动 其实就是两种方式 在io方式下访问PCI/SRIO设备 通过outbound寄存器将本地存储器映射到remote端pci设备 --------------------------------IOMMU过程 同时一般需要将CPU物理地址转换成…

PCI驱动使用函数

PCI总线驱动 1.pci驱动注册 pci_register_driver(struct pci_driver *drv) static struct pci_driver hamachi_driver { .name DRV_NAME, .id_table hamachi_pci_tbl, .probe hamachi_init_one, .remove …

linux 查看 pci 设备驱动,如何写linux pci设备驱动程序

PCI总线应用领域及其广泛并且令人惊奇。不同的pci设备有不同的需求以及不同的问题。因此,在linux内核中pci层支持就非常重要啦。本文档就是想为驱动程序设计开发人员解决pci处理中的各种问题。 0.Pci设备驱动程序的结构 现在有两种风格的的pci驱动程序结构:新风格的驱动(即让…

linux 内核PCI驱动总结记录

1. 介绍 Peripheral ComponentInterconnect (PCI,外围设备互联)。总线由电气接口、编程接口组成。主要讨论编程接口。最常用的总线,内核支持最好的总线。ISA裸金属总线,电子爱好者偏爱。 2. PCI的特点 是一种完整的规范,定义…

linux驱动程序之PCI驱动程序设计

文章目录 PCI驱动描述PCI驱动注册使能PCI设备获取PCI配置寄存器基地址中断部分代码 PCI驱动描述 在linux内核中,PCI驱动使用 struct pic_driver 结构来描述: struct pci_driver {/*以上还有很多成员*///id_table 中包含了PCI设备的相关信息const struc…

PCI驱动编程

一、字符设备和块设备 Linux抽象了对硬件的处理,所有的硬件设备都可以像普通文件一样来看待:它们可以使用和操作文件相同的、标准的系统调用接口来完成打开、关闭、读写和I/O控制操作,而驱动程序的主要任务也就是要实现这些系统调用函数。Li…