SylixOS_x86_PCI串口驱动浅析

1. 适用范围

    本文仅针对于3.0及上版本的SylixOS x86平台PCI转串口相关驱动架构进行简单的分析。

2. PCI简介

    外部链接标准(或称个人电脑界面,Personal Computer Interface),实际应用中简称为PCI(Peripheral Component Interconnect),是一种连接电脑主板和外部设备的总线标准。一般PCI装置可分为以下两种形式:

    直接内建于主板上的集成电路,在PCI规范中称作“嵌入装置”(planar device);或者安装在插槽上的扩充界面卡。

    PCI 总线见于现代的个人电脑中,并已取代了ISA和VESA局部总线,成为了标准扩充总线。PCI总线亦常见于其他电脑类型中。PCI总线最终将被PCI Express和其他更先进的技术取代,这些技术现在已经被用于最新款的电脑中。

    PCI规范规定了该总线的物理尺寸(包括线宽)、电气特性、总线时序和协议。该规范可从美国PCI-SIG协会购得。

    常见的PCI卡包括网络卡、声卡、调变解调器(调制解调器)、电视卡和硬盘控制器等,另外还有USB和串列埠等端口。原本显卡通常也是PCI装置,但很快其频宽已不足以支援显卡的性能。PCI显卡现在仅用在需要额外的外接显示器或主板上没有AGP和PCI Express槽的情况。

3. PCI串口卡简介

    串口卡主要是用来扩展PC的串口数量和种类。常见的x86机器主板上可能只有一个或者两个RS232的串口接口,在某些场景下不能满足对串口的需求,于是就有了PCI串口卡。通常PCI串口卡会支持拓展2至8个串口,也会支持RS232,RS485,RS422这几种串口格式。PCI串口卡在工业和军工领域运用广泛。

4. PCI串口驱动架构分析

4.1      SylixOS下一般的PCI驱动架构

    在x86的base工程libsylixos/SylixOS/driver/pci/null路径下,提供了SylixOS PCI驱动示例:pciNullDev.c。

        pciNullDev.c中主要实现了如表 4‑1所示五个主体框架函数。

表 4‑1  pciNullDev.c中主体函数

函数名 函数功能
pciNullDevInit PCI设备驱动初始化
pciNullDevProbe PCI设备ID探测和资源信息初始化
pciNullDevRemove 删除PCI设备
pciNullDevIdTblGet 获取PCI设备ID表的表头与表头大小
pciNullDevIsr PCI设备驱动中断服务程序
  • 函数pciNullDevInit

        该函数主要用来初始化PCI设备驱动,其调用pciNullDevIdTblGet等函数将相关的PCI设备结构体填充完成,并调用API_PciDrvRegister函数注册PCI设备驱动。

  • 函数pciNullDevProbe

        该函数由SylixOS PCI子系统回调,主要完成更新设备驱动版本信息,设备索引号,获取设备MEM、IO、IRQ等资源信息以及中断连接与使能操作。

  • 函数pciNullDevRemove

        该函数由SylixOS PCI子系统回调,主要完成删除PCI设备的一系列操作,在该示例中没有实现相关功能代码。

  • 函数pciNullDevIdTblGet

        该函数主要由pciNullDevInit函数调用,用来获取相关PCI设备的ID表的表头与表的大小。

  • 函数pciNullDevIsr

        该函数为驱动服务函数,主要提供了该PCI设备驱动的中断服务处理,在该示例中中断服务处理没有实现相关功能代码。

        pciNullDev.c示例中的PCI设备驱动的流程如图 4‑1所示:

SylixOS_x86_PCI串口驱动浅析_第1张图片

图 4‑1  pciNullDev.c设备驱动大致流程

4.2      SylixOS下PCI串口设备的驱动架构

    在x86的base工程libsylixos/SylixOS/driver/pci/sio路径存放的是PCI串口卡驱动。pciSioExar.c和pciSioNetmos.c均是PCI串口卡的驱动,是针对不同厂商的适配。一般PCI串口卡都是使用了16c500这一系列的串口芯片,这里着重分析pciSioNetmos.c。

4.2.1   PCI设备ID表

    如程序清单 4‑1所示pciSioNetmos.c中有一个驱动支持的设备ID表结构体数组。PCI驱动通过PCI总线获取设备相关ID数据和驱动中的驱动支持设备ID表来匹配加载相关的驱动。

程序清单 4‑1  驱动支持设备ID表

/*********************************************************************************************************
  驱动支持的设备 ID 表, 用于驱动与设备进行自动匹配, 与 Linux 参数保持一致.
*********************************************************************************************************/
static const PCI_DEV_ID_CB  pciSioNetmosIdTbl[] = {
    {
        PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9901,
        0xa000, 0x1000, 0, 0,
        netmos_9912
    },
    {
        PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9912,
        0xa000, 0x1000, 0, 0,
        netmos_9912
    },
    {
        PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9922,
        0xa000, 0x1000, 0, 0,
        netmos_9912
    },
    {
        PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9904,
        0xa000, 0x1000, 0, 0,
        netmos_9912
    },
    {
        PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9900,
        0xa000, 0x1000, 0, 0,
        netmos_9912
    },
    {
    }                                                            /* terminate list            */
};

    如程序清单 4‑2,在x86的base工程libsylixos/SylixOS/system/drvice/pci/pciDrv.h中定义了设备ID表数据结构体PCI_DEV_ID_CB,其中包含厂商ID,设备ID,子厂商ID,子设备ID,设备类,设备子类,设备私有数据这7个相关属性,与Linux的PCI结构一致。

程序清单 4‑2  驱动支持设备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;

4.2.2   函数介绍

    如表 4‑2所示在pciSioNetmos.c除了实现了和示例驱动中类似的Init、Probe、Remove、IdTblGet、Isr这五个相关类型的函数外,还实现了其他的设备相关驱动的函数。

表 4-2  pciSioNetmos.c实现的相关函数

函数名 函数功能
pciSioNetmosInit PCI NETMOS 16c550 控制器驱动相关初始化
pciSioNetmosProbe PCI NETMOS 16c550 板卡驱动探测设备
pciSioNetmosRemove 总线上移除 PCI 设备
pciSioNetmosIdTblGet 获取PCI设备ID表的表头与表头大小
pciSioNetmosChan 创建一个 SIO 通道
pciSioNetmosIsr PCI设备驱动中断服务程序
pciSioNetmosGetReg 获得 NETMOS 16C550 寄存器的值
pciSioNetmosGetReg 设置 NETMOS 16C550 寄存器
  • 函数pciSioNetmosInit

        该函数和pciNullDevInit一样,调用pciNullDevIdTblGet获取驱动支持设备ID表的表头和大小,并设置驱动名为“pci_netmos”,pciSioNetmosProbe和pciSioNetmosRemove复制给PCI设备驱动控制块,调用API_PciDrvRegister函数注册PCI设备驱动。

  • 函数pciSioNetmosProbe

        该函数通过驱动设置的参数获取设备MEM的其实地址和MEM的大小,通过调用API_PciDevIoRemap重新映射驱动的内存空间地址,根据驱动设置的参数获取设备中断资源并注册,启动PCI总线的主模式,并调用pciSioNetmosChan函数来初始化串口设备的通道参数,最后通过ttyDevCreate函数创建出串口设备。

  • 函数pciSioNetmosRemove

        和函数pciNullDevRemove一样,实现总线上移除PCI设备时的处理,这里在pciSioNetmos.c里面没有实现相关方法。

  • 函数pciSioNetmosIdTblGet

        和pciNullDevIdTblGet一样,用来从驱动支持设备ID表中获取相关PCI设备的ID表的表头与表的大小。

  • 函数pciSioNetmosChan

        PCI串口驱动的关键函数,该函数将PCI设备驱动和串口设备驱动相互连接起来了。将驱动设置好的串口参数,PCI串口的中断和pciSioNetmosSetReg,pciSioNetmosGetReg函数赋值给PCI设备串口通道结构体,调用API_PciDevInterDisable先禁能PCI串口设备的中断,然后调用系统的16c550串口驱动中的sio16c550Init来初始化相关PCI串口通道,随后调用API_PciDevInterConnect,API_PciDevInterEnable连接并使能PCI串口设备中断,完成PCI串口通道的创建。

  • 函数pciSioNetmosIsr

        PCI串口的中断服务函数,该函数是在PCI设备的中断函数服务中调用了系统的16c550串口驱动服务函数,来完成对应的串口中断处理事务。

  • 函数pciSioNetmosGetReg

        该函数被系统串口驱动回调,用于读取PCI设备对应通道相关寄存器地址的值。

  • 函数pciSioNetmosSetReg

        该函数被系统串口驱动回调,用于设置PCI设备对应通道相关寄存器地址的值。

    pciSioNetmos.c示例中的PCI设备驱动的函数结构如图 4‑4所示:

SylixOS_x86_PCI串口驱动浅析_第2张图片

图 4‑4  pciSioNetmos.c设备驱动大体流程

5. 总结

    PCI串口驱动本质上是PCI驱动和串口驱动的一个结合,上层通过系统的串口驱动来封装出串口所需要的操作接口,下层由PCI驱动来和PCI总线上的设备进行各种操作。

转载于:https://my.oschina.net/senjienly/blog/838992

你可能感兴趣的:(SylixOS_x86_PCI串口驱动浅析)