自定义 PCI 驱动程序无法探测设备

标签 c linux-kernel linux-device-driver kernel-module pci

init_module 函数中调用 pci_register_driver() 注册 PCI 驱动程序后,驱动程序应该控制任何还没有驱动程序的 PCI 设备,假设设备与 struct pci_device_id 中指定的供应商 ID、设备 ID 等匹配。

我想强制以太网 Controller 使用我的驱动程序,只是为了实验(例如读取配置字节)。在 Virtualbox 客户机(Mint,内核 3.13.0)上,我将以太网 Controller 的驱动程序列入黑名单,运行 update-initramfs -u,然后重新启动。这成功地解除了默认驱动程序与 Controller 的关联,因为该驱动程序不再出现在 lspci -k 的输出中。

然而,当我加载模块时,一些以前丢失的设备出现在 lspci -k 的输出中(由我的驱动程序控制它们),但是以太网 Controller 仍然缺少一个“正在使用的内核驱动程序:” 行。如何让我的模块识别并拥有 Controller ?

请注意,我对供应商和设备字段使用了 PCI_ANY_ID,并且未初始化 struct pci_device_id 的其他字段。所以我希望驱动程序能够探测当前缺少驱动程序的任何设备。

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/pci.h>

MODULE_LICENSE("GPL");

int init_module(void);
void cleanup_module(void);
static int pci_probe(struct pci_dev *, const struct pci_device_id *);
static void pci_remove(struct pci_dev *dev);

#define SUCCESS 0
#define FAILURE -1


static struct pci_device_id my_pci_id = {
        .vendor = PCI_ANY_ID,
        .device = PCI_ANY_ID
};

static struct pci_driver my_pci_driver = {
        .name = "kmod_driver",
        .id_table = &my_pci_id,
        .probe = pci_probe,
        .remove = pci_remove
};


int init_module(void)
{
        return pci_register_driver(&my_pci_driver);
}

void cleanup_module(void)
{
        pci_unregister_driver(&my_pci_driver);
}

static int pci_probe(struct pci_dev *dev, const pci_device_id *id)
{
        int enableStatus = pci_enable_device(dev);
        .....
        return SUCCESS;
}

static void pci_remove(struct pci_dev *dev)
{
        return;
}

最佳答案

您还需要包括 subvendorsubdevice 字段(也将它们设置为 PCI_ANY_ID)。匹配函数是这样的:

static inline const struct pci_device_id *
pci_match_one_device(const struct pci_device_id *id, const struct pci_dev *dev)
{
        if ((id->vendor == PCI_ANY_ID || id->vendor == dev->vendor) &&
            (id->device == PCI_ANY_ID || id->device == dev->device) &&
            (id->subvendor == PCI_ANY_ID || id->subvendor == dev->subsystem_vendor) &&
            (id->subdevice == PCI_ANY_ID || id->subdevice == dev->subsystem_device) &&
            !((id->class ^ dev->class) & id->class_mask))
                return id;
        return NULL;
}

您可以使用 PCI_DEVICE 宏来提供适当的 sub 成员:

static struct pci_device_id my_pci_id = {
    PCI_DEVICE(PCI_ANY_ID, PCI_ANY_ID),
};

关于自定义 PCI 驱动程序无法探测设备,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38799867/

相关文章:

c++ - 选择期间的sqlite科学记数法

linux - linux中低速发送数据包

linux-kernel - kmalloc 中的缓冲区也是 DMA 安全缓冲区吗?

linux - 早期启动调度极其脆弱

macos - 内存是否被锁定(固定)?

linux-kernel - 编译器/链接器如何解析内核 API,例如从 linux 上的模块调用的 'printk'

c - 系统调用不同的硬件架构?

c - 带有源列表的 MPI_Recv

计算数组大小

linux-kernel - 如何使用wake_up_interruptible