2016-08-06 19 views
1

После регистрации драйвера PCI по телефону pci_register_driver() в функции init_module драйвер должен взять под контроль любые устройства PCI, у которых еще нет драйверов, при условии, что устройства соответствуют идентификатору поставщика, идентификатор устройства и т. д., как указано в struct pci_device_id.Пользовательский драйвер PCI не может обнаружить устройство

Я хотел бы заставить контроллер Ethernet использовать мой драйвер только для экспериментов (например, чтение байтов конфигурации). В гостевой системе Virtualbox (Mint, kernel 3.13.0) я занес в черный список драйвер контроллера Ethernet, запустил update-initramfs -u и перезагрузился. Это успешно отключило драйвер по умолчанию от контроллера, поскольку драйвер больше не отображался на выходе lspci -k.

Однако, когда я загрузил модуль, на выходе lspci -k появилось несколько устройств (с моим драйвером, управляющим ими), но Ethernet-контроллеру по-прежнему не хватало линии "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

Вы не можете просто сказать ЛЮБЫЕ ЛЮБЫЕ для поставщика и идентификатора устройства. Вы должны указать фактического поставщика/устройства (и, возможно, идентификаторы суб-поставщика/под-устройства) для устройства, которым вы хотите управлять с помощью этого вашего драйвера. –

+0

@ChaitanyaLala, это не всегда так. Многие драйверы соответствуют классу, например. AHCI, 8250, ... – 0andriy

+0

'.vendor = PCI_ANY_ID, .device = PCI_ANY_ID' означает, что ваш драйвер будет проверен на первое устройство _matching_. У первого подходящего устройства, скорее всего, может быть уже загружен драйвер. – 0andriy

ответ

0

Вы также должны включать subvendor и subdevice поля (настройка их 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), 
};