您好,登錄后才能下訂單哦!
本文僅針對于3.0及上版本的SylixOS x86平臺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槽的情況。
串口卡主要是用來擴展PC的串口數量和種類。常見的x86機器主板上可能只有一個或者兩個RS232的串口接口,在某些場景下不能滿足對串口的需求,于是就有了PCI串口卡。通常PCI串口卡會支持拓展2至8個串口,也會支持RS232,RS485,RS422這幾種串口格式。PCI串口卡在工業和軍工領域運用廣泛。
在x86的base工程libsylixos/SylixOS/driver/pci/null路徑下,提供了SylixOS PCI驅動示例:pciNullDev.c。
pciNullDev.c中主要實現了如表 41所示五個主體框架函數。
表 41 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設備驅動的流程如圖 41所示:
圖 41 pciNullDev.c設備驅動大致流程
在x86的base工程libsylixos/SylixOS/driver/pci/sio路徑存放的是PCI串口卡驅動。pciSioExar.c和pciSioNetmos.c均是PCI串口卡的驅動,是針對不同廠商的適配。一般PCI串口卡都是使用了16c500這一系列的串口芯片,這里著重分析pciSioNetmos.c。
如程序清單 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;
如表 42所示在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設備驅動的函數結構如圖 44所示:
圖 44 pciSioNetmos.c設備驅動大體流程
PCI串口驅動本質上是PCI驅動和串口驅動的一個結合,上層通過系統的串口驅動來封裝出串口所需要的操作接口,下層由PCI驅動來和PCI總線上的設備進行各種操作。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。