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

gewenbin
gewenbin
gewenbin
188
文章
15
评论
2021年3月30日13:14:13 评论 807

SylixOS PCIe设备驱动注册和卸载

在SylixOS中,使用PCI_DRV_CB 数据结构来表示一个PCIe设备驱动:

typedef struct {
    LW_LIST_LINE            PCIDRV_lineDrvNode;                         /* 驱动节点管理                 */
    CHAR                    PCIDRV_cDrvName[PCI_DRV_NAME_MAX];          /* 驱动名称                     */
    PVOID                   PCIDRV_pvPriv;                              /* 私有数据                     */
    PCI_DEV_ID_HANDLE       PCIDRV_hDrvIdTable;                         /* 设备支持列表                 */
    UINT32                  PCIDRV_uiDrvIdTableSize;                    /* 设备支持列表大小             */

    /*
     *  驱动常用函数, PCIDRV_pfuncDevProbe 与 PCIDRV_pfuncDevRemove 不能为 LW_NULL, 其它可选
     */
    INT   (*PCIDRV_pfuncDevProbe)(PCI_DEV_HANDLE hHandle, const PCI_DEV_ID_HANDLE hIdEntry);
    VOID  (*PCIDRV_pfuncDevRemove)(PCI_DEV_HANDLE hHandle);
    INT   (*PCIDRV_pfuncDevSuspend)(PCI_DEV_HANDLE hHandle, PCI_PM_MESSAGE_HANDLE hPmMsg);
    INT   (*PCIDRV_pfuncDevSuspendLate)(PCI_DEV_HANDLE hHandle, PCI_PM_MESSAGE_HANDLE hPmMsg);
    INT   (*PCIDRV_pfuncDevResumeEarly)(PCI_DEV_HANDLE hHandle);
    INT   (*PCIDRV_pfuncDevResume)(PCI_DEV_HANDLE hHandle);
    VOID  (*PCIDRV_pfuncDevShutdown)(PCI_DEV_HANDLE hHandle);

    PCI_ERROR_HANDLE        PCIDRV_hDrvErrHandler;                      /* 错误处理句柄                 */

    INT                     PCIDRV_iDrvFlag;                            /* 驱动标志                     */
    UINT32                  PCIDRV_uiDrvDevNum;                         /* 关联设备数                   */
    LW_LIST_LINE_HEADER     PCIDRV_plineDrvDevHeader;                   /* 设备管理链表头               */
} PCI_DRV_CB;
typedef PCI_DRV_CB         *PCI_DRV_HANDLE;

我们这里关注一下几个重要的成员:

  • PCIDRV_cDrvName:驱动名字,这个必须是系统所有PCIe驱动中唯一的,这个名字同时也是使用picdev pcidrv 命令时显示出的名字。
  • PCIDRV_hDrvIdTable:驱动支持的设备ID列表,驱动和设备通过此表进行匹配,这个会在后续章节详解。
  • PCIDRV_uiDrvIdTableSize:设备ID表中条目个数。
  • PCIDRV_pfuncDevProbe:驱动注册回调函数,注册时会调用此接口进行设备初始化的工作,需要驱动开发者实现。
  • PCIDRV_pfuncDevRemove:驱动卸载回调函数,卸载时会调用此接口进行资源回收工作,需要驱动开发者实现。

 

一般在驱动中定义一个全局变量来表示:

static PCI_DRV_CB pci_driver;

然后初始化其驱动名字成员:

#define PCI_DRV_NAME "pci_demo_drv"

strlcpy(pci_driver.PCIDRV_cDrvName, PCI_DRV_NAME, PCI_DRV_NAME_MAX);

通过API_PciDrvRegister 这个接口来注册PCIe设备驱动,这个接口的原型为:

INT API_PciDrvRegister(PCI_DRV_HANDLE hHandle);

初始化好pci_driver 之后,将其地址传入上述函数即可注册驱动:

API_PciDrvRegister(&pci_driver);

驱动卸载需要经过两步操作,首先需要通过驱动名字找到内核使用的驱动控制块,因为在驱动注册时内核会生成一个自己的驱动控制块,然后将驱动中我们自己定义的pci_driver数据结构中所有信息复制过去。卸载时需要使用内核自己生成的驱动控制块而不是我们自己定义的。通过API_PciDrvHandleGet 接口我们可以获得内核的驱动控制块:

PCI_DRV_HANDLE pci_driver;

pci_driver = API_PciDrvHandleGet(PCI_DRV_NAME);

然后使用API_PciDrvUnregister 接口即可卸载驱动:

API_PciDrvUnregister(pci_driver);

附源码

pci_driver_demo1.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_DRV_CB pci_driver;

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日13:14:13
  • 转载请务必保留本文链接:http://www.databusworld.cn/10068.html
匿名

发表评论

匿名网友 填写信息

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