首页 > 技术文章 > MODULE_DEVICE_TABLE 的作用

ancongliang 2017-11-15 13:45 原文

pci_device_id,PCI设备类型的标识符。在include/linux/mod_devicetable.h头文件中定义。
struct pci_device_id {
        __u32 vendor, device;           /* Vendor and device ID or PCI_ANY_ID*/
        __u32 subvendor, subdevice;     /* Subsystem ID's or PCI_ANY_ID */
        __u32 class, class_mask;        /* (class,subclass,prog-if) triplet */
        kernel_ulong_t driver_data;     /* Data private to the driver */
};
PCI设备的vendor、device和class的值都是预先定义好的,通过这些参数可以唯一确定设备厂商和设备类型。这些PCI设备的标准值在include/linux/pci_ids.h头文件中定义。
pci_device_id需要导出到用户空间,使模块装载系统在装载模块时知道什么模块对应什么硬件设备。宏MODULE_DEVICE_TABLE()完成该工作。
设备id一般用数组形式。如:

  • static struct pci_device_id rtl8139_pci_tbl[] = {
            {0x10ec, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
            ....
    };
    MODULE_DEVICE_TABLE (pci, rtl8139_pci_tbl);
  • static struct pci_device_id e1000_pci_tbl[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x1000) },
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x1001) },
        {0,}
    };
    MODULE_DEVICE_TABLE (pci, e1000_pci_tbl); 

该语句创建一个名为__mod_pci_device_table的局部变量,只想struct pci_device_id数组。在稍后的内核构建过程中,depmod程序在所有的模块中搜索符号__mod_pci_device_table。如果找到了该符号,它把数据从该模块中抽出,添加到文件/lib/module/KERNEL_VERSION/module.pcimap中。当depmod结束之后,内核模块支持的所有PCI设备连同他们的模块名都在改文件中被列出。当内核告知热插拔系统一个新的PCI设备已经被发现时,热插拔系统使用module.pcimap文件来寻找要加载的适当的驱动程序。

MODULE_DEVICE_TABLE的第一个参数是设备的类型,如果是USB设备,那自然是usb(如果是PCI设备,那将是pci,这两个子系统用同一个宏来注册所支持的设备)。后面一个参数是设备表,这个设备表的最后一个元素是空的,用于标识结束。例:假如代码定义了USB_SKEL_VENDOR_ID是 0xfff0,USB_SKEL_PRODUCT_ID是0xfff0,也就是说,当有一个设备接到集线器时,usb子系统就会检查这个设备的 vendor ID和product ID,如果他们的值是0xfff0时,那么子系统就会调用这个模块作为设备的驱动。

 

http://www.ibm.com/developerworks/cn/linux/l-usb/index2.html

当usb设备插入时,为了使linux-hotplug(Linux中PCI、USB等设备热插拔支持)系统自动装载驱动程序,你需要创建一个MODULE_DEVICE_TABLE。代码如下(这个模块仅支持某一特定设备):

/* table of devices that work with this driver */
static struct usb_device_id skel_table [] = {
    { USB_DEVICE(USB_SKEL_VENDOR_ID,
      USB_SKEL_PRODUCT_ID) },
    { }                      /* Terminating entry */
};
MODULE_DEVICE_TABLE (usb, skel_table);

USB_DEVICE宏利用厂商ID和产品ID为我们提供了一个设备的唯一标识。当系统插入一个ID匹配的USB设备到USB总线时,驱动会在USB core中注册。驱动程序中probe 函数也就会被调用。usb_device 结构指针、接口号和接口ID都会被传递到函数中。

static void * skel_probe(struct usb_device *dev,
unsigned int ifnum, const struct usb_device_id *id)

驱动程序需要确认插入的设备是否可以被接受,如果不接受,或者在初始化的过程中发生任何错误,probe函数返回一个NULL值。否则返回一个含有设备驱动程序状态的指针。通过这个指针,就可以访问所有结构中的回调函数。

推荐阅读