SylixOS PCIe设备ID匹配
我们知道声卡有声卡的驱动,网卡有网卡的驱动,那么我们在加载声卡驱动的时候,系统是怎么知道当前的驱动是给声卡这个设备用的而不是给网卡用的呢?这就是通过驱动中定义的设备ID表来识别的。
驱动中的设备表用来标明本驱动支持哪些PCIe设备,在加载驱动的时候,会将系统中所有的PCIe设备和驱动中的ID表进行匹配,如果匹配上了则调用驱动中的probe初始化函数。在SylixOS下使用PCI_DEV_ID_CB 这个数据结构来表示设备ID信息:
typedef struct { UINT32 PCIDEVID_uiVendor; /* 厂商 ID */ UINT32 PCIDEVID_uiDevice; /* 设备 ID */ UINT32 PCIDEVID_uiSubVendor; /* 子厂商 ID */ UINT32 PCIDEVID_uiSubDevice; /* 子设备 ID */ UINT32 PCIDEVID_uiClass; /* 设备类 */ UINT32 PCIDEVID_uiClassMask; /* 设备子类 */ ULONG PCIDEVID_ulData; /* 设备私有数据 */ } PCI_DEV_ID_CB; typedef PCI_DEV_ID_CB *PCI_DEV_ID_HANDLE;
一般的PCIe设备通过厂商ID和设备ID来匹配驱动,所以在驱动中需要将这两个成员设置在表中。我们以x86模拟器中的PCIe设备进行讲解:
通过pcis 我们可以查看到系统中有一个显卡设备,厂商ID为0x1013,设备ID为0xb8,现在我们想为其写驱动,那么我们就需要驱动中定义一个设备表,然后将这个显卡的厂商ID和设备ID设置在表中:
static PCI_DEV_ID_CB pci_devices[] = { {PCI_DEVICE(0x1013, 0x00b8)}, {} };
这样驱动加载时只有符合这两个ID条件的设备才会使用本驱动,设备ID表设置完之后还需要将其地址设置到pci_driver中:
static PCI_DRV_CB pci_driver = { .PCIDRV_hDrvIdTable = (PCI_DEV_ID_HANDLE)pci_devices, .PCIDRV_uiDrvIdTableSize = sizeof(pci_devices) / sizeof(PCI_DEV_ID_CB), };
PCIDRV_uiDrvIdTableSize表示设备ID表中有几个设备,在实际的驱动中,有可能一个厂商有N个设备都可以使用同一个驱动,但是这些设备的ID是不一样的,所以需要在表中设置多个设备:
附源码
pci_driver_demo2.c源码:
#define __SYLIXOS_KERNEL #define __SYLIXOS_PCI_DRV #include <SylixOS.h> #include <module.h> #include <string.h> #include <stdio.h> #include <stdlib.h> #include <linux/compat.h> #include <system/device/pci/pciBus.h> #include <system/device/pci/pciMsi.h> #include <system/device/pci/pciLib.h> #include <system/device/pci/pciIds.h> #include <system/device/pci/pciDev.h> #define PCI_DRV_NAME "pci_demo_drv" static PCI_DEV_ID_CB pci_devices[] = { {PCI_DEVICE(0x1013, 0x00b8)}, {} }; static PCI_DRV_CB pci_driver = { .PCIDRV_hDrvIdTable = (PCI_DEV_ID_HANDLE)pci_devices, .PCIDRV_uiDrvIdTableSize = sizeof(pci_devices) / sizeof(PCI_DEV_ID_CB), }; int module_init (void) { strlcpy(pci_driver.PCIDRV_cDrvName, PCI_DRV_NAME, PCI_DRV_NAME_MAX); API_PciDrvRegister(&pci_driver); return 0; } void module_exit (void) { PCI_DRV_HANDLE pci_driver; pci_driver = API_PciDrvHandleGet(PCI_DRV_NAME); API_PciDrvUnregister(pci_driver); }
评论