「深入探索Linux的PCI驱动」

1. PCI驱动介绍

Peripherals Component Interconnect(PCI)是一种本地计算机总线标准,是一种用于连接计算机内部硬件设备的总线标准。PCI总线可在计算机的主板上提供连接,支持其他卡或板,如网卡,声卡,显卡等硬件扩展插件。

在Linux中,与PCI硬件交互的驱动程序称为PCI驱动程序,它是内核中的一部分。PCI驱动程序管理Linux内核和PCI卡之间的通信。PCI驱动程序的目的是将Linux内核的机制与PCI设备的硬件功能结合起来。

1.1 PCI驱动的注册和注销

PCI驱动程序的注册并不是一个自动的过程。每当内核加载一个PCI驱动程序时,驱动程序都需要向内核发出请求来注册它。同样,当驱动程序完成操作和处理后,驱动程序也需要向内核发出请求来注销它。

要注册PCI驱动程序,必须创建一个struct pci_driver对象,并使用pci_register_driver()函数向内核注册它。在驱动程序不再需要处理PCI设备时,使用pci_unregister_driver()函数可以将其从内核中注销。

static struct pci_driver pci_driver = {

.name = "driver-name",

.id_table = pci_device_id_table,

.probe = driver_probe,

.remove = driver_remove,

};

static int __init driver_init(void)

{

return pci_register_driver(&pci_driver);

}

static void __exit driver_exit(void)

{

pci_unregister_driver(&pci_driver);

}

2. PCI设备的访问方式

当一个PCI设备被检测到并加载了相应的PCI驱动程序后,PCI设备就可以被操作系统访问和控制。为了访问PCI设备,驱动程序需要保存一个对struct pci_dev结构的引用。它是内核中用于表示PCI设备的结构体。

2.1 PCI配置空间

在Linux下,要访问PCI设备的寄存器,必须首先访问PCI配置空间。

对PCI设备的访问是通过读写PCI配置空间寄存器进行的。要读取配置寄存器,需要使用pci_read_config_{byte, word, dword}()函数,而要写入配置寄存器,需要使用pci_write_config_{byte, word, dword}()函数。

以下是一个示例代码,用于在pci设备上读取和写入配置信息:

static int pci_probe(struct pci_dev *pdev,

const struct pci_device_id *ent)

{

int err;

u8 value;

err = pci_enable_device(pdev);

if (err)

goto err;

/* Read from configuration space */

pci_read_config_byte(pdev, PCI_CLASS_REVISION, &value);

/* Write to configuration space */

pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, 0x01);

return 0;

err:

return err;

}

2.2 PCI内存映射IO

PCI内存映射IO(MMIO)是Linux内核中PCI设备和CPU之间进行通信的最常用方法之一。PCI设备驱动程序使用ioremap()函数将显存映射到内存中,驱动程序通过获取对物理地址指针的访问权限来读写内存。

/* PCI设备驱动程序进行映射 */

static int pci_probe(struct pci_dev *pdev,

const struct pci_device_id *ent)

{

int err;

struct pci_bar bar;

void __iomem *ioaddr;

if (pci_request_region(pdev, BAR_NUM, "my_label")) {

printk(KERN_ERR "Unable to get PCI BAR 0\n");

goto err;

}

pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &bar.base_addr);

pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0 + 4, &bar.length);

bar.base_addr &= PCI_BASE_ADDRESS_MEM_MASK;

bar.length = ~(bar.length & PCI_BASE_ADDRESS_IO_MASK) + 1;

ioaddr = ioremap(bar.base_addr, bar.length);

// ...

pci_release_region(pdev, BAR_NUM);

return 0;

err:

return err;

}

3. 总结

PCI驱动程序是非常重要的,因为它们允许Linux内核与PCI硬件设备进行通信。最常用的方法是通过MMIO的方式进行通信。使用PCI驱动程序,可以从操作系统中访问PCI的硬件资源。在Linux下,要访问PCI设备的寄存器,必须首先访问PCI配置空间。驱动程序需要使用pci_read_config_{byte, word, dword}()函数来读取配置寄存器,并使用pci_write_config_{byte, word, dword}()函数来写入配置寄存器。

免责声明:本文来自互联网,本站所有信息(包括但不限于文字、视频、音频、数据及图表),不保证该信息的准确性、真实性、完整性、有效性、及时性、原创性等,版权归属于原作者,如无意侵犯媒体或个人知识产权,请来电或致函告之,本站将在第一时间处理。猿码集站发布此文目的在于促进信息交流,此文观点与本站立场无关,不承担任何责任。

操作系统标签