2016-08-06 212 views
1

通過在init_module函數中調用pci_register_driver()註冊PCI驅動程序之後,驅動程序應該控制任何尚未具有驅動程序的PCI設備,假設設備與供應商ID匹配,設備ID等,如struct pci_device_id中所述。自定義PCI驅動程序無法探測設備

我想強制以太網控制器使用我的驅動程序,只是爲了實驗(例如讀取配置字節)。在Virtualbox guest虛擬機(Mint,內核3.13.0)上,我列出了以太網控制器的驅動程序,運行update-initramfs -u,然後重新啓動。因爲驅動程序不再出現在lspci -k的輸出中,所以這成功地將默認驅動程序與控制器分離。

但是,當我加載模塊時,以前丟失的一些設備出現在lspci -k的輸出中(我的驅動程序控制它們),但以太網控制器仍然缺少"Kernel driver in use: "線路。我怎樣才能讓我的模塊識別並擁有控制器?

請注意,我使用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; 
} 
+0

你不能只是說什麼,對於任何廠商和設備ID。您必須爲要通過該驅動程序控制的設備指定實際的供應商/設備(以及可能的子供應商/子設備ID)。 –

+0

@ChaitanyaLala,情況並非總是如此。許多司機按類別匹配,例如AHCI,8250,... – 0andriy

+0

'.vendor = PCI_ANY_ID,.device = PCI_ANY_ID'表示您的驅動程序將針對第一個_matching_設備進行探測。第一個匹配設備很可能可能已經加載了驅動程序。 – 0andriy

回答

0

您還需要包括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), 
};