设备驱动中的pci(kernel-4.7)

本文介绍了PCI总线架构的组成部分,包括PCI设备、PCI总线和PCI桥。在Linux内核4.7中,PCI设备的枚举探测过程涉及PCI设备的识别、PCI总线的结构以及PCI设备与驱动的匹配方法。通过children、devices和ops等关键结构体,内核能够自动探测并注册所有连接的PCI设备。
摘要由CSDN通过智能技术生成

PCI 总线架构主要被分成三部分:
1.PCI 设备。
符合 PCI 总线标准的设备就被称为 PCI 设备,PCI 总线架构中可以包含多个 PCI 设备。Audio 、LAN 都是一个 PCI 设备。PCI 设备同时也分为主设备和目标设备两种,主设备是一次访问操作的发起者,而目标设备则是被访问者。

2.PCI 总线。
PCI 总线在系统中可以有多条,类似于树状结构进行扩展,每条 PCI 总线都可以连接多个 PCI 设备/ 桥。

3.PCI 桥。当一条 PCI 总线的承载量不够时,可以用新的 PCI 总线进行扩展,而 PCI 桥则是连接 PCI 总线之间的纽带。

这里写图片描述

在内核中与PCI相关的结构体大概有pci_driverpci_device_idpci_devpci_bus,PCI总线都是指的pci_bus


struct pci_bus {
    struct list_head node;      /* node in list of buses */
    struct pci_bus  *parent;    /* parent bus this bridge is on */
    struct list_head children;  /* list of child buses */
    struct list_head devices;   /* list of devices on this bus */
    struct pci_dev  *self;      /* bridge device as seen by parent */
    struct list_head slots;     /* list of slots on this bus;
                       protected by pci_slot_mutex */
    struct resource *resource[PCI_BRIDGE_RESOURCE_NUM];
    struct list_head resources; /* address space routed to this bus */
    struct resource busn_res;   /* bus numbers routed to this bus */

    struct pci_ops  *ops;       /* configuration access functions */
    struct msi_controller *msi; /* MSI controller */
    void        *sysdata;   /* hook for sys-specific extension */
    struct proc_dir_entry *procdir; /* directory entry in /proc/bus/pci */

    unsigned char   number;     /* bus number */
    unsigned char   primary;    /* number of primary bridge */
    unsigned char   max_bus_speed;  /* enum pci_bus_speed */
    unsigned char   cur_bus_speed;  /* enum pci_bus_speed */
#ifdef CONFIG_PCI_DOMAINS_GENERIC
    int     domain_nr;
#endif

    char        name[48];

    unsigned short  bridge_ctl; /* manage NO_ISA/FBB/et al behaviors */
    pci_bus_flags_t bus_flags;  /* inherited by child buses */
    struct device       *bridge;
    struct device       dev;
    struct bin_attribute    *legacy_io; /* legacy I/O for this bus */
    struct bin_attribute    *legacy_mem; /* legacy mem */
    unsigned int        is_added:1;
};

几个重要的成员:
children: PCI桥可以使当前总线得到扩展,当前总线上有几个PCI桥,那么当前总线就会拥有几个子总线,子总线会连接到父总线的children链表中。
devices: 连接在这条总线上的设备链表。
ops: 当前总线访问总线上设备配置空间的 read、write 方法。PCI总线的操作结构体pci_ops 如下:


/* Low-level architecture-dependent routines */

struct pci_ops {
    int (*add_bus)(struct pci_bus *bus);
    void (*remove_bus)(struct pci_bus *bus);
    void __iomem *(*map_bus)(struct pci_bus *bus, unsigned int devfn, int where);
    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级总线,然后枚举探测0级总线上的设备,如果是PCI桥,那么还要进入下一级子总线,最终所有的连接的PCI设备都将被探测到,详细的探测过程,我们在后边分析。

每个PCI设备都由一组参数唯一地标识,这些参数保存在结构体pci_device_id中 ,该结构体定义在include/linux/mod_devicetable.h中:


struct pci_device_id {
    __u32 vendor, device;       /* Vendor and device ID or PCI_ANY_ID*/
    __u32 subvendor, subdevice; /* Subsystem ID's or PCI_ANY_ID */
    __u32 class, class_mask;    /* (class,subclass,prog-if) triplet */
    kernel_ulong_t driver_data; /* Data private to the driver */
};

pci_driver 结构体主要的是用于识别设备的id_table结构,以及用于检测设备的函数probe( )和卸载设备的函数remove( )

struct pci_driver {
    struct list_head node;
    const char *name;
    const struct pci_device_id *id_table;   /* must be non-NULL for probe to be called */
    int  (*probe)  (struct pci_dev *dev, 
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值