SylixOS PCIe设备驱动开发(十三)

gewenbin
gewenbin
gewenbin
188
文章
15
评论
2021年3月30日15:09:16 评论 798

SylixOS PCIe设备驱动注册和卸载入口

通过前面的介绍我们知道当驱动注册时,如果匹配通过会调用我们自己的probe初始化函数,同样在卸载时会调用我们自己的退出函数。我们先来看看我们自己的probe函数:

static int pci_driver_probe (PCI_DEV_HANDLE pci_dev, const PCI_DEV_ID_HANDLE id)
{
    return 0;
}

在SylixOS中,使用PCI_DEV_CB 来表示一个PCIe设备,在系统启动过程中,会扫描系统中所有的PCIe设备并为每一个PCIe设备生成一个PCI_DEV_CB 数据结构:

typedef struct {
    LW_LIST_LINE        PCIDEV_lineDevNode;                             /* 设备管理节点                 */
    LW_OBJECT_HANDLE    PCIDEV_hDevLock;                                /* 设备自身操作锁               */

    UINT32              PCIDEV_uiDevVersion;                            /* 设备版本                     */
    UINT32              PCIDEV_uiUnitNumber;                            /* 设备编号                     */
    CHAR                PCIDEV_cDevName[PCI_DEV_NAME_MAX];              /* 设备名称                     */

    INT                 PCIDEV_iDevBus;                                 /* 总线号                       */
    INT                 PCIDEV_iDevDevice;                              /* 设备号                       */
    INT                 PCIDEV_iDevFunction;                            /* 功能号                       */
    PCI_HDR             PCIDEV_phDevHdr;                                /* 设备头                       */

    /*
     *  PCI_HEADER_TYPE_NORMAL  PCI_HEADER_TYPE_BRIDGE  PCI_HEADER_TYPE_CARDBUS
     */
    INT                 PCIDEV_iType;                                   /* 设备类型                     */
    UINT8               PCIDEV_ucPin;                                   /* 中断引脚                     */
    UINT8               PCIDEV_ucLine;                                  /* 中断线                       */
    UINT32              PCIDEV_uiIrq;                                   /* 虚拟中断向量号               */

    UINT8               PCIDEV_ucRomBaseReg;
    UINT32              PCIDEV_uiResourceNum;
    PCI_RESOURCE_CB     PCIDEV_tResource[PCI_NUM_RESOURCES];            /* I/O and memory  + ROMs       */

    INT                 PCIDEV_iDevIrqMsiEn;                            /* 是否使能 MSI                 */
    ULONG               PCIDEV_ulDevIrqVector;                          /* MSI 或 INTx 中断向量         */
    UINT32              PCIDEV_uiDevIrqMsiNum;                          /* MSI 中断数量                 */
    PCI_MSI_DESC        PCIDEV_pmdDevIrqMsiDesc;                        /* MSI 中断描述                 */

    CHAR                PCIDEV_cDevIrqName[PCI_DEV_IRQ_NAME_MAX];       /* 中断名称                     */
    PINT_SVR_ROUTINE    PCIDEV_pfuncDevIrqHandle;                       /* 中断服务句柄                 */
    PVOID               PCIDEV_pvDevIrqArg;                             /* 中断服务参数                 */

    PVOID               PCIDEV_pvDevDriver;                             /* 驱动句柄                     */
    PVOID               PCIDEV_pvPrivate;                               /* 用户驱动使用                 */
} PCI_DEV_CB;
typedef PCI_DEV_CB     *PCI_DEV_HANDLE;

通过上述结构信息我们可以看出从这个数据结构中包含了很多信息,比如设备在总线上的位置、中断号、资源等等。通过资源成员我们可以获取设备各个BAR空间中的起始地址和大小,这个在下一章节详解。

probe函数的第二个入参表示当前设备的ID信息。类似probe函数,我们来看看自己定义的退出函数:

static void pci_driver_remove (PCI_DEV_HANDLE pci_dev)
{

}

这两个函数定义完之后,还需要将其设置到pri_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_pfuncDevProbe    = pci_driver_probe,
    .PCIDRV_pfuncDevRemove   = pci_driver_remove,
};

我们可以在probe和remove函数中加调试信息然后在模拟器中加载驱动观察输出效果:

static int pci_driver_probe (PCI_DEV_HANDLE pci_dev, const PCI_DEV_ID_HANDLE id)
{
    printk("probe: bus %d, dev %d, func %d.\r\n",
            pci_dev->PCIDEV_iDevBus,
            pci_dev->PCIDEV_iDevDevice,
            pci_dev->PCIDEV_iDevFunction);

    return 0;
}

static void pci_driver_remove (PCI_DEV_HANDLE pci_dev)
{
    printk("remove: bus %d, dev %d, func %d.\r\n",
            pci_dev->PCIDEV_iDevBus,
            pci_dev->PCIDEV_iDevDevice,
            pci_dev->PCIDEV_iDevFunction);
}

编译驱动上传x86模拟器然后加载驱动:

insmod /lib/modules/pci_driver_demo3.ko

可以在模拟器上看到probe函数中的打印:

SylixOS PCIe设备驱动开发(十三)

使用pcidev和pcidrv可以查看到驱动的信息:

SylixOS PCIe设备驱动开发(十三)

卸载驱动查看打印信息:

rmmod /lib/modules/pci_driver_demo3.ko

可以在模拟器上看到remove函数中的打印:

SylixOS PCIe设备驱动开发(十三)

 

附源码

pci_driver_demo3.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 int pci_driver_probe (PCI_DEV_HANDLE pci_dev, const PCI_DEV_ID_HANDLE id)
{
    printk("probe: bus %d, dev %d, func %d.\r\n",
            pci_dev->PCIDEV_iDevBus,
            pci_dev->PCIDEV_iDevDevice,
            pci_dev->PCIDEV_iDevFunction);

    return 0;
}

static void pci_driver_remove (PCI_DEV_HANDLE pci_dev)
{
    printk("remove: bus %d, dev %d, func %d.\r\n",
            pci_dev->PCIDEV_iDevBus,
            pci_dev->PCIDEV_iDevDevice,
            pci_dev->PCIDEV_iDevFunction);
}

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_pfuncDevProbe    = pci_driver_probe,
    .PCIDRV_pfuncDevRemove   = pci_driver_remove,
};

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);
}

 

gewenbin
  • 本文由 发表于 2021年3月30日15:09:16
  • 转载请务必保留本文链接:http://www.databusworld.cn/10074.html
匿名

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: