PCIE内核注册详解

代码结构

在Linux内核中,PCIe驱动程序的注册和处理涉及到许多文件,其中一些主要的文件包括:

  1. drivers/pci/pci.h:这个文件定义了PCIe驱动程序结构体和相关的函数。驱动程序需要包含这个头文件才能使用PCIe相关的函数和结构体。

  2. drivers/pci/pci-driver.c:这个文件包含了PCIe驱动程序的核心注册函数pci_register_driver()pci_unregister_driver()。这些函数用于向内核注册和注销PCIe驱动程序。

  3. drivers/pci/probe.c:这个文件包含了PCIe设备探测相关的函数。当系统检测到一个新的PCIe设备时,内核会调用这些函数来确定是否有与该设备匹配的驱动程序。

  4. drivers/pci/pci.c:这个文件包含了PCIe设备初始化相关的函数。一旦驱动程序被匹配到一个PCIe设备,内核会调用这些函数来初始化设备并分配资源。

  5. drivers/pci/pci-sysfs.c:这个文件包含了用于PCIe设备驱动程序的sysfs接口相关的函数。sysfs接口允许用户空间应用程序查询和控制PCIe设备和驱动程序的状态。

  6. arch/x86/pci/pci.c(或者对应架构的文件):这个文件包含了PCIe设备的中断处理函数。当PCIe设备产生中断时,内核会调用这个函数来处理中断。

这些文件涵盖了PCIe驱动程序在内核中注册和处理的主要方面。但是,PCIe驱动程序的具体实现可能会涉及到其他文件和头文件。

代码解读

pcie
这是Linux内核中的PCIe驱动程序初始化代码。以下是每个部分的功能:

  1. struct bus_type pcie_port_bus_type:定义了一个名为pci_express的总线类型,表示PCIe总线。它还包含一个指向pcie_port_bus_match()函数的指针,用于在PCIe总线上匹配设备。

  2. EXPORT_SYMBOL_GPL(pcie_port_bus_type):将pcie_port_bus_type结构体导出为GPL符号,以便其他内核模块可以使用它。

  3. bus_register(&pci_bus_type):注册PCI总线类型,将PCI驱动程序与PCI总线关联起来。

  4. bus_register(&pcie_port_bus_type):如果内核配置中启用了PCIe端口总线,则注册PCIe总线类型,将PCIe端口驱动程序与PCIe总线关联起来。

  5. dma_debug_add_bus(&pci_bus_type):将PCI总线类型添加到DMA调试器中,以便可以跟踪PCI总线上的DMA操作。

  6. postcore_initcall(pci_driver_init):将pci_driver_init()函数添加到内核的后核心初始化调用列表中,以便在内核启动时自动调用该函数。

这个初始化代码在内核启动时运行,用于将PCI和PCIe端口驱动程序注册到内核中,以便它们可以与PCI和PCIe总线进行通信。

struct bus_type pci_bus_type = {
	.name		= "pci",
	.match		= pci_bus_match,
	.uevent		= pci_uevent,
	.probe		= pci_device_probe,
	.remove		= pci_device_remove,
	.shutdown	= pci_device_shutdown,
	.dev_groups	= pci_dev_groups,
	.bus_groups	= pci_bus_groups,
	.drv_groups	= pci_drv_groups,
	.pm		= PCI_PM_OPS_PTR,
	.num_vf		= pci_bus_num_vf,
	.dma_configure	= pci_dma_configure,
};
EXPORT_SYMBOL(pci_bus_type);

这是Linux内核中的PCI总线类型结构体定义和初始化代码。以下是每个部分的功能:

  1. struct bus_type pci_bus_type:定义了一个名为pci的总线类型,表示PCI总线。它还包含一些指向函数的指针,用于处理PCI设备驱动程序、总线事件和电源管理等方面。

  2. .name = "pci":设置总线类型名称为pci

  3. .match = pci_bus_match:设置匹配函数指针,当新设备连接到PCI总线时会调用该函数进行匹配操作。

  4. .uevent = pci_uevent:设置uevent回调函数指针,当PCI设备状态发生变化时会调用该回调函数发送事件通知给用户空间。

  5. .probe = pci_device_probe, .remove = pci_device_remove, .shutdown = pci_device_shutdown, .dev_groups = pci_dev_groups, .bus_groups = pci_bus_groups, .drv_groups = pci_drv_groups: 这些都是处理 PCI 设备驱动程序相关操作的回调函数指针。其中 probe 函数在新设备连接到 PCI 总线上时被调用;remove 函数在从 PCI 总线上移除一个设备时被调用;shutdown 函数在系统关闭或重启时被调用以释放资源;dev_groups、bus_groups 和 drv_group 三个成员变量分别表示了与 PCI 设备、PCI 总线和 PCI 驱动程序相关联的 sysfs 属性组。

  6. .pm = PCI_PM_OPS_PTR:设置电源管理回调函数指针,用于实现 PCI 设备的省电模式。

  7. .num_vf = pci_bus_num_vf:设置虚拟化相关的回调函数指针,用于处理 SR-IOV 相关操作。

  8. .dma_configure = pci_dma_configure:设置 DMA 相关回调函数指针,用于配置 PCI 设备的 DMA 策略。

  9. EXPORT_SYMBOL(pci_bus_type):将pci_bus_type结构体导出为符号,以便其他内核模块可以使用它。

这个初始化代码定义了PCI总线类型结构体,并将其导出为符号。当新设备连接到PCI总线时,内核会自动使用这个结构体中定义的函数进行匹配和驱动程序加载等操作。

新设备注册流程

在Linux内核中,注册PCIe设备的函数调用栈如下:

  1. 驱动程序调用pci_register_driver()函数向内核注册PCI驱动程序。
  2. 当PCI子系统探测到一个新的PCI设备时,会调用pci_device_probe()函数探测设备,并在设备匹配成功后调用驱动程序的probe()函数。
  3. probe()函数中,驱动程序会调用pci_request_regions()函数请求PCI设备的IO和内存地址空间。
  4. 驱动程序会调用pci_enable_device()函数启用PCI设备,包括启用设备的中断和总线主控制器。
  5. 驱动程序会调用pci_set_master()函数设置PCI设备为总线主控制器。
  6. 驱动程序会调用pci_iomap()函数映射PCI设备的IO和内存地址空间。
  7. 驱动程序会调用pci_enable_msi()pci_enable_msix()函数启用设备的MSI或MSI-X中断。
  8. 驱动程序会调用dev_set_drvdata()函数将私有数据保存到设备结构体中。
  9. 驱动程序会调用device_create_file()函数创建设备属性文件,例如/sys/bus/pci/devices/xxx/xxx文件。
  10. 驱动程序会调用dma_set_mask_and_coherent()函数设置DMA掩码。
  11. 最后,驱动程序会调用pci_set_drvdata()函数将私有数据保存到设备结构体中。

在上述过程中,驱动程序需要实现probe()函数和remove()函数,分别用于设备探测和设备移除操作。
此外,驱动程序还需要实现struct pci_driver结构体,其中包含了驱动程序的一些信息,例如支持的设备ID、厂商ID等等。
在驱动程序中,可以使用pci_register_driver()函数将驱动程序注册到PCI子系统中,从而使得驱动程序能够正确地探测和管理PCIe设备。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值