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中主要實現瞭如表 41所示五個主體框架函數。

表 41  pciNullDev.c中主體函數

函數名函數功能
pciNullDevInitPCI設備驅動初始化
pciNullDevProbePCI設備ID探測和資源信息初始化
pciNullDevRemove刪除PCI設備
pciNullDevIdTblGet獲取PCI設備ID表的表頭與表頭大小
pciNullDevIsrPCI設備驅動中斷服務程序
  • 函數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設備驅動的流程如圖 41所示:

圖 41  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表

    如程序清單 41所示pciSioNetmos.c中有一個驅動支持的設備ID表結構體數組。PCI驅動通過PCI總線獲取設備相關ID數據和驅動中的驅動支持設備ID表來匹配加載相關的驅動。

程序清單 41  驅動支持設備ID表

/*********************************************************************************************************
  驅動支持的設備 ID 表, 用於驅動與設備進行自動匹配, 與 Linux 參數保持一致.
*********************************************************************************************************/
staticconstPCI_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
    },
    {
    }                                                                   /* terminatelist               */
}

    如程序清單 42,在x86的base工程libsylixos/SylixOS/system/drvice/pci/pciDrv.h中定義了設備ID表數據結構體PCI_DEV_ID_CB,其中包含廠商ID,設備ID,子廠商ID,子設備ID,設備類,設備子類,設備私有數據這7個相關屬性,與Linux的PCI結構一致。

程序清單 42  驅動支持設備ID表結構體

/*********************************************************************************************************
  驅動支持設備列表控制塊
*********************************************************************************************************/
typedefstruct {
    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   函數介紹

    如表 42所示在pciSioNetmos.c除了實現了和示例驅動中類似的Init、Probe、Remove、IdTblGet、Isr這五個相關類型的函數外,還實現了其他的設備相關驅動的函數。

表 4-2  pciSioNetmos.c實現的相關函數

函數名函數功能
pciSioNetmosInitPCI NETMOS 16c550 控制器驅動相關初始化
pciSioNetmosProbePCI NETMOS 16c550 板卡驅動探測設備
pciSioNetmosRemove總線上移除 PCI 設備
pciSioNetmosIdTblGet獲取PCI設備ID表的表頭與表頭大小
pciSioNetmosChan創建一個 SIO 通道
pciSioNetmosIsrPCI設備驅動中斷服務程序
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設備驅動的函數結構如圖 44所示:

圖 44  pciSioNetmos.c設備驅動大體流程

5. 總結

    PCI串口驅動本質上是PCI驅動和串口驅動的一個結合,上層通過系統的串口驅動來封裝出串口所需要的操作接口,下層由PCI驅動來和PCI總線上的設備進行各種操作。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章