赞
踩
__pci_set_master
- static void __pci_set_master(struct pci_dev *dev, bool enable)
- {
- u16 old_cmd, cmd;
-
- pci_read_config_word(dev, PCI_COMMAND, &old_cmd); // 读取设备的PCI命令寄存器的当前值
- if (enable)
- cmd = old_cmd | PCI_COMMAND_MASTER; // 如果要启用总线主控,设置命令字相应的位
- else
- cmd = old_cmd & ~PCI_COMMAND_MASTER; // 如果要禁用总线主控,清除命令字相应的位
- if (cmd != old_cmd) { // 如果命令字有变化,更新PCI命令寄存器
- pci_dbg(dev, "%s bus mastering\n",
- enable ? "enabling" : "disabling");
- pci_write_config_word(dev, PCI_COMMAND, cmd);
- }
- dev->is_busmaster = enable; // 更新设备的状态,表示总线主控是否被启用
- }
这个函数专注于设置或清除PCI命令寄存器中控制总线主控的位。如果启用,它会设置这个位;如果禁用,它会清除这个位。更新操作只会在这个位的状态实际改变时发生。
pcibios_set_master
函数和 pci_set_master
函数- // pcibios_set_master函数为PCI设备dev启用总线主控。这是默认实现。如果需要,体系结构特定的实现可以覆盖此函数。
- void __weak pcibios_set_master(struct pci_dev *dev)
- {
- u8 lat;
-
- // PCIe设备(无论是Type 0还是Type 1)不适用延迟定时器
- if (pci_is_pcie(dev))
- return;
-
- pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat); // 读取延迟定时器的当前值
- if (lat < 16)
- lat = (64 <= pcibios_max_latency) ? 64 : pcibios_max_latency;// 如果小于16,设置一个默认值或最大值
- else if (lat > pcibios_max_latency)
- lat = pcibios_max_latency; // 如果大于最大值,降到最大值
- else
- return;
-
- pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat); // 写回修改后的延迟定时器值
- }
-
- // pci_set_master函数用于启用PCI设备dev的总线主控。
- void pci_set_master(struct pci_dev *dev)
- {
- __pci_set_master(dev, true); // 启用总线主控
- pcibios_set_master(dev); // 调用体系结构特定的设置
- }
- EXPORT_SYMBOL(pci_set_master);
pcibios_set_master
函数是用来做一些体系结构特定的总线主控设置的。它检查并可能会调整PCI设备的延迟定时器值以避免PCI总线拥塞。
pci_set_master
函数则是一个更高级的接口,通常由驱动程序调用以启用设备的总线主控功能,并随后调用`pcibios_set_master`函数完成体系结构相关的设置。通过EXPORT_SYMBOL宏,这个函数被导出,使得其他内核模块可以调用它。
在 Linux 内核中,`pci_set_master()` 函数用于使能给定 PCI 设备的 Bus Mastering 功能。Bus Mastering 是一种允许连接到总线的设备(如 PCI 设备)直接访问系统内存,无需通过 CPU 的机制。这对于一些需要快速数据传输的设备来说非常重要,比如网络卡或 SCSI 控制器。
当你的驱动程序控制着某个 PCI 设备时,你可能需要调用 pci_set_master() 来允许设备发起 DMA(Direct Memory Access)传输。
函数的声明如下:
void pci_set_master(struct pci_dev *dev);
其中,`struct pci_dev *dev` 是一个指向 PCI 设备的结构。
以下是在驱动程序中如何使用 pci_set_master() 函数的一个简单示例:
- #include <linux/pci.h>
-
- int enable_pci_device(struct pci_dev *pdev) {
- int ret;
-
- // 首先,启用 PCI 设备
- ret = pci_enable_device(pdev);
- if (ret) {
- pr_err("Failed to enable PCI device\n");
- return ret;
- }
-
- // 设置 PCI 设备为 Bus Master
- pci_set_master(pdev);
-
- // 其他初始化任务...
-
- return 0;
- }
在这个示例里,首先调用 pci_enable_device() 启用 PCI 设备。只有设备被启用后,才能调用 pci_set_master(),后者会设置设备的 COMMAND 寄存器来允许 Bus Mastering。
如果你的 PCI 设备使用 DMA,通常还需要分配并设置 DMA 缓冲区,以及可能的 DMA 映射操作,以确保 DMA 传输能够正确执行。在 Linux 驱动开发中,你可能需要使用更多的 DMA 相关 API 来进行这些操作。
在Linux内核中,pci_set_master是一个用于设置PCI设备为主设备的函数。当你希望一个PCI设备能够发起DMA操作到系统内存或其他PCI设备的内存时,你需要将它设置为主设备。
pci_set_master函数通常在PCI驱动程序的初始化部分被调用,以确保设备可以执行DMA操作。
以下是pci_set_master函数的原型:
int pci_set_master(struct pci_dev *dev);
其中,dev是一个指向pci_dev结构的指针,该结构表示一个PCI设备。
如果函数调用成功,它将返回0。如果设置主设备失败,它将返回一个负的错误代码。
下面是一个简单的例子,展示了如何在PCI驱动中使用pci_set_master:
- #include <linux/pci.h>
- #include <linux/init.h>
- #include <linux/module.h>
-
- static int __init my_pci_driver_init(void)
- {
- struct pci_dev *dev;
- int err;
-
- /* 查找我们的PCI设备 */
- dev = pci_get_device(PCI_VENDOR_ID, PCI_DEVICE_ID, NULL);
- if (!dev) {
- printk(KERN_ERR "Unable to find PCI device\n");
- return -ENODEV;
- }
-
- /* 使设备成为主设备 */
- err = pci_set_master(dev);
- if (err) {
- printk(KERN_ERR "Failed to set PCI device as master\n");
- pci_dev_put(dev);
- return err;
- }
-
- /* ... 其他初始化代码 ... */
-
- return 0;
- }
-
- static void __exit my_pci_driver_exit(void)
- {
- /* 清理代码 */
- }
- module_init(my_pci_driver_init);
- module_exit(my_pci_driver_exit);
- MODULE_LICENSE("Dual BSD/GPL");
在这个例子中,我们首先使用pci_get_device来查找我们的PCI设备。然后,我们调用pci_set_master来设置该设备为主设备。如果设置失败,我们打印一个错误消息并退出。如果成功,我们可以继续进行其他的初始化操作。
注意:在使用PCI设备时,你还需要处理其他许多事情,如内存映射、中断处理等。上面的代码只是一个简单的示例,用于说明如何使用pci_set_master函数。在实际驱动开发中,你需要确保遵循所有相关的Linux内核编程惯例和最佳实践。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。