PCI驱动程序(第十二章 )

1、PCI(Peripheral Component Interconnect) 外围设备互联
2、PCI接口
(1)PCI寻址:每个PCI外设由一个总线编号,一个设备编号及一个功能编号来标识( biāo zhì 同“标志”,“①表明特征的记号。②表明某种特征。”)。
(2)在显示硬件地址时,有时显示为两个值(一个8位的总线编号和一个8位的设备及功能编号),有时显示为三个值(总线、设备和功能),有时显示为四个值(域、总线、设备和功能)。
3、引导阶段
(1)PCI字节序是小端的。
(2)用三个或者五个PCI寄存器可标识一个设备:vendorID、deviceID和class是常用的三个寄存器。有时厂商还利用subsystem vendorID和subSystem deviceID两个字段来进一步区分相似的设备。
     vendorID:16位寄存器,用于标识硬件制造商
     deviceID:16位寄存器,由制造商选择,无需对设备ID进行官方注册,通常与厂商ID配对成唯一一个32位硬件设备标识符。
     class
     subsystem vendorID
     subsystem deviceID
struct pci_device_id结构体用于定义该驱动程序支持的不同类型的PCI设备列表。包含以下字段:
     __u32 vendor;
     __u32 device;
他们指定了设备的PCI厂商和设备ID。如果驱动程序可以处理任何厂商或者设备ID,这些字段应该使用值PCI_ANY_ID.
     __u32 subvendor;
     __u32 subdevice;
     他们制定了设备的PCI子系统厂商和子系统设备ID。如果驱动程序可以处理任何类型的子系统ID,这些字段应该使用值PCI_ANY_ID
     __u32 class;
     __u32 class_mask;
     kernel_ulong_t driver_data;
应该使用两个辅助的宏来进行struct pci_device_id结构砼的初始化:
     PCI_DEVICE(vendor, device);
     PCI_DEVICE_CLASS(device_class, device_class_mask);
4、MODULE_DEVICE_TABLE:完成将pci_device_id结构体需要被导出到用户控件的工作。
5、注册PCI驱动程序:
     为了正确注册带内核,所有的PCI驱动程序都必须创建的主要结构体是:struct pci_devicer结构体。该结构体由许多回调函数和变量组成。下面列出需要注意的字段:
     const char *name;
     const struct pci_device_id *id_table;
     int (*probe) (struct pci_dev *dev, const strcut pci_device_id *id);
     void (*remove) (struct pci_dev *dev);
     int (*suspend) (struct pci_dev *dev);
     int (*resume) (struct pci_dev *dev);
注:前四个字段是必须要初始化的。
     struct pci_driver注册于卸载:
     例如:
     static int __init pci_skel_init(void)
     {
          return pci_register_driver(&pci_driver);
     }

     static void __exit pci_skel_exit(void)
     {
          pci_unregister_driver(&pci_driver);
     }
6、老式PCI探测
     如果真的需要查找特定PCI设备的能力的话,可以使用下面的函数:
(1)struct pci_dev *pci_get_device(unsigned int vendor, unsigned int device, struct pci_dev *from);
(2)struct pci_dev *pci_get_subsys(unsigned int vendor, unsigned int device, unsigned int ss_vendor, unsigned int ss_device, struct pci_dev *from);
(3)strcut pci_dev *pci_get_slot(struct pci_bus *bus, unsigned int devfn);
7、激活PCI设备
     int pci_enable_device(struct pci_dev *dev);
8、访问配置空间
     函数原型定义在<linux/pci.h>
     int pci_read_config_byte(struct pci_dev *dev, int where, u8 *val);
     int pci_read_config_word(struct pci_dev *dev, int where, u16 *val);
     int pci_read_config_dword(struct pci_dev *dev, int where, u32 *val);
     word和dword函数会将读取到的little-endian值转换成处理器固有的字节序,因此无需我们转换。
     int pci_write_config_byte(struct pci_dev *dev, int where, u8 val);
     int pci_write_config_word(struct pci_dev *dev, int where, u16 val);
     int pci_write_config_dword(struct pci_dev *dev, int where, u32 val);
     word和dword函数在把值写入外设之前,会将其换换成小字节序。上面的6个函数都实现为inline函数,他们实际上调用下面的函数:
     int pci_bus_read_config_byte(struct pci_bus *bus, unsigned int devfn, int where, u8 *val);
     int pci_bus_read_config_word(struct pci_bus *bus, unsigned int devfn, int where, u16 *val);
     int pci_bus_read_config_dword(struct pci_bus *bus, unsigned int devfn, int where, u32 *val);
     int pci_bus_write_config_byte(struct pci_bus *bus, unsigned int devfn, int where, u8 *val);
     int pci_bus_write_config_world(struct pci_bus *bus, unsigned int devfn, int where, u16 *val);
     int pci_bus_write_config_dword(struct pci_bus *bus, unsigned int devfn, int where, u32 *val);
9、访问I/O和内存空间
     在内核中,PCI设备的I/O区域已经被集成到通用资源管理,我们无需访问配置变量来了解设备映射到内存或I/O空间的何处,获取区域信息的首选接口由如下函数组成:
     unsigned long pci_resource_start(strcut pci_dev *dev, int bar);
     unsigned long pci_resource_end(struct pci_dev *dev, int bar);
     unsigned long pci_resource_flags(struct pci_dev *dev, int bar);
     flags标志定义在<linux/ioport.h>中,下面是最重要的几个:
     IORESOURCE_IO:
     IORESOURCE_MEM:
     IORESOURCE_PREFETCH:
     IORESOURCE_READONLY:
10、PCI中断
11、硬件抽象:
     配置寄存器访问的相关结构仅包含2个字段:
     struct pci_ops {
          int (*read) (struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *val);
          int (*write) (struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *val);
     };
     
     
     
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值