摘 要:本文首先從整體上分析VxWorks 網卡驅動程序的原理和結構,然后深入地分析Rtl8139C網卡驅動程序的結構以及實現,本文對于VxWorks下的同類開發也有一定參考作用。
關鍵詞:網卡驅動程序;VxWorks;嵌入式系統;Tornado
1引言
VxWorks是當前應用十分廣泛的嵌入式實時操作系統,而網卡在基于VxWorks的開發中有著極其重要的作用。Tornado 是VxWorks的開發工具,它本身支持的網卡不多。本文涉及到的網卡是Realtek 公司的8139C PCI網卡,相關的硬件資料有:RTL8139C(L) data sheet 和 Rtl8139 Programming Guide 。需要實現的是RTL8139C END driver 。
2 VxWorks簡介
VxWorks是由WRS(Wind River System Inc.)公司開發的一套具有微內核、高性能、可伸縮的實時操作系統,支持廣泛的網絡通信協議,并能夠根據用戶的需求進行組合。其開放式的結構和對工業標準的支持使開發者只需做少的工作即可設計出有效的適合于不同用戶要求的系統。
VxWorks是一種功能強大而且比較復雜的操作系統,VxWorks只占用了很小的存儲空間,并可高度裁減,保證了系統能以較高的效率運行。所以僅僅依靠人工編程調試,很難發揮它的功能并設計出可靠、高效的嵌入式系統,必須要有與之相適應的開發工具。TornadoII是為開發VxWorks應用系統提供的集成開發環境。
VxWorks的特性為編寫應用程序和設備驅動程序提供了極大的便利。在VxWorks下,設備驅動程序既可以嵌入到內核中隨系統一起啟動,也可以作為可加載模塊在系統啟動之后運行。網卡驅動程序一般采用前一種方式。
3 VxWorks的網絡模型
網卡在VxWorks開發中是極其重要的。在開發機-目標機模式中,通過網線進行下載調試是Tornado調試器常用方便的方式。VxWorks的的實時性能使其在網絡通信當中具有極廣泛的應用,如網絡交換機、路由器的軟件系統等。
網卡驅動程序在整個VxWorks網絡接口中的角色可以從下圖中看出。
整個網絡接口呈層次結構,用戶網絡應用程序通過socket接口調用TCP/IP協議層系列軟件,網卡驅動程序則為協議軟件提供對網卡的訪問。VxWorks也為網卡驅動程序進行了分層,其中老式的BSD4.3驅動程序的功能,現在可以由協議層驅動、MUX層和END驅動實現。而且,工作于BSD的以太網網卡不支持系統級調試,而工作于END的網卡同時支持任務級調試和系統級調試。很顯然,網卡驅動程序的層次結構使網卡驅動程序的實現和移植更加方便。而且,VxWorks 為編寫網卡增強型驅動程序(Enhanced Network Drivers)提供了很好的接口和規范。
4 Rtl8139C END驅動程序
4.1 PCI局部總線
本文涉及到的網卡是Realtek 公司的8139C PCI網卡,作為一個PCI設備,在設備的初始化階段,它和一般的PCI設備沒有什么不同。
每一個PCI局部總線目標設備都由一個配置寄存器空間,它使目標設備的配置十分簡便。配置空間是一個容量為256字節并具有特定記錄結構或模型的地址空間。該空間有分為頭標區和設備有關區兩部分。設備在每個區中只實現必要的和與之相配的寄存器。一個設備的配置空間不僅在系統自舉時可以訪問,而且在其他時間內也是可以訪問的。
4.2數據包結構
VxWorks MUX層的數據包采用的是mBlk-clBlk-cluster 結構,如圖。發送時,網卡發送模塊處理的是這樣的結構;接收數據時,網卡還得將數據通過這樣的結構傳遞給上層協議。不過,這一切Vxworks 都有相應的規范和函數。另外,mBlk和clBlk可以由netpool 結構管理,VxWorks 提供一系列接口函數。
4.3驅動程序的結構以及流程
1、網卡的探測以及入口
VxWorks BSP在syslib.c中探測并初始化系統中的PCI設備,檢測設備的I/O映射地址,內存映射地址以及中斷向量和級別,這些硬件參數對于主芯片的讀寫和連接中斷起到至關重要的作用。因此,在這里加入8139C 網卡的探測模塊。然后將探測到的參數傳遞給驅動程序入口函數。
網卡的探測模塊為sysRtl8139PciInit模塊,利用的是RTL8139C的廠商標識和設備標識,在所有的PCI設備中判斷有幾塊這樣的網卡,得到它們的功能號,總線號和設備號,然后配置它的PCI配置空間,將網卡寄存器映射。得到網卡I/O映射基地址和Mem基地址以及中斷向量和級別。
2、入口函數
END driver與系統的接口是MUX層,BSP對于網卡設備的驅動是通過MuxDevLoad()對endDevTbl[](configNet.h中)的處理來實現的。因此,可以將一個自定義的入口函數加到endDevTbl[],這樣就可以使驅動程序在合適的時間對設備進行初始化。
驅動程序的入口分為兩個步驟,他們分別是sysRtl8139EndLoad模塊和Rtl8139EndLoad模塊。sysRtl8139EndLoad獲得sysRtl8139PciInit 探測到網卡硬件參數,并且兩次調用Rtl8139EndLoad模塊。Rtl8139EndLoad模塊次被調用時只是為了返回設備名稱。
在Rtl8139EndLoad入口函數中,解析參數,為網卡的DMA工作方式分配一定大小的空間,寫寄存器,準備工作。這之后,網卡的開始工作和停止,以及其他設置完全由MUX 層管理,驅程只需要將一系列模塊的指針傳遞給它。這些模塊按照MUX 層的要求是一個 NET_FUNCS 結構,如下所示。
LOCAL NET_FUNCS rtlFuncTable =
{
(FUNCPTR)rtl8139Start, /* start func. */
(FUNCPTR)rtl8139Stop, /* stop func. */
(FUNCPTR)rtl8139Unload, /* unload func. */
(FUNCPTR)rtl8139Ioctl, /* ioctl func. */
(FUNCPTR)rtl8139Send, /* send func. */
(FUNCPTR)rtl8139MCastAddrAdd,/* multicast add func. */
(FUNCPTR)rtl8139MCastAddrDel,/* multicast delete func. */
(FUNCPTR)rtl8139MCastAddrGet,/* multicast get fun. */
(FUNCPTR)rtl8139PollSend, /* polling send func. */
(FUNCPTR)rtl8139PollReceive, /* polling receive func. */
endEtherAddressForm, /* put address info into a NET_BUFFER */
endEtherPacketDataGet, /* get pointer to data in NET_BUFFER */
endEtherPacketAddrGet,/*Get packet addresses. */
};
Rtl8139EndLoad 模塊是rtl8139.c中的外部函數,當程序流程到達這里的時候,已經可以對網卡寄存器讀寫,程序完全是對寄存器進行設置。在這個模塊中,首先判斷函數參數,因為它被調用兩次。當確定是第二次調用時,首先為驅動程序分配一個結構RTL8139END_DEVICE,用以存儲共享參數。然后解析函數參數,依據這些參數配置RTL8139END_DEVICE。接著,調用rtl8139InitMem模塊,為網卡分配所需要的內存,將這些參數寫進RTL8139END_DEVICE。這樣,網卡所需的資源齊全了。用上層協議提供的函數END_OBJ_INIT和END_MIB_INIT,將RTL8139END_DEVICE 和驅動程序模塊傳遞給上層協議。
需要為網卡分配的內存包括:接收區,發送區,cluster區,mBlk,clBlk和管理它們的netpool。這些都是在Rtl8139InitMem模塊中完成。
3、網卡的啟動和關閉
網卡要開始工作,還得依賴MUX層調用rtl8139Start模塊,該模塊將中斷向量和處理函數連接在一起。然后調用硬件初始化rtl8139HwStart模塊,在這個模塊中,設置接收地址寄存器,使其能管理接受區,寫設置寄存器,設置網卡的工作方式,寫中斷屏蔽寄存器,確定處理哪些中斷。,寫命令寄存器,使接受和發送位有效。程序到此,就能產生中斷,并進行處理。
當系統要退出或者其他原因時,就得關閉網卡。系統是調用通過MUX層中的rtl8139Stop模塊完成。
4、中斷處理程序
RTL8139C 有一個中斷狀態寄存器和一個中斷屏蔽寄存器,它們對應位意義相同。中斷狀態寄存器反映了網卡能產生的幾種中斷。一旦有中斷發生,中斷處理函數首先屏蔽中斷,再分析中斷狀態寄存器,調用相應的處理函數
只要中斷發生,系統調用中斷處理函數。中斷處理函數的主要功能是分析中斷狀態寄存器,進行相應的處理。依據RTL8139 Programming Guide 中的說明,若是發送中斷,無論成功與否,調用發送處理函數,若是接收中斷,開辟新的接受任務,這么做是因為中斷處理函數運行在系統級,而接收處理較復雜耗時,所以采用系統函數netJobAdd開辟新的任務。而簡單的處理就直接在中斷處理函數中完成,包括發送完后產生的中斷。
由于,處理函數在執行的過程中,新的中斷可能出現,而此時中斷已屏蔽,但各自的狀態位依然變化。因此,在中斷處理函數中采用循環結構,直到中斷狀態寄存器表明在處理過程中沒有新的中斷發生。
5、數據接收和發送
接收數據時,從相應的寄存器取出當前數據包的地址,首先分析數據包頭部,包括數據包的接收狀態和大小。如果是錯誤的狀態,就使命令寄存器中的接收能位失效,再使其有效,這可看作接收重啟,再重新設置與接收相關的寄存器。如果接收的數據包正常,接收處理函數就得按照數據包的大小將數據包拷貝到cluster 區(Rtl8139InitMem 模塊中分配),用mBlk-clBlk-cluster結構傳遞給上層協議,并刷新寄存器使其指向下一個數據包。然后,讀命令寄存器,判斷是否接收完畢,否則循環。
發送數據時,由于Rtl8139采用四個描述符寄存器和四個狀態寄存器。所以在使用它們前首先判斷是否有空閑的寄存器,如果沒有,就得等待一段時間。在這段時間里,如果有寄存器空閑出來,就開始發送數據,否則退出。發送時,只要將上層協議傳遞過來的mBlk-clBlk-cluster中的cluster數據拷貝到發送區,寫描述符寄存器就可。而記錄每個描述符寄存器使用情況,就使用RTL8139END_DEVICE 結構中的一個數組。如果發送完畢,無論成功與否,都得讓描述符空閑出來。
5結束語
本文具體的分析了Rtl8139C網卡驅動程序在VxWorks操作系統下的實現。在分析過程中,更多側重PCI網卡END驅動程序在VxWorks下實現的共性,包括必需的配置和步驟,比如PCI設備的相關工作以及VxWorks下MUX層的數據包結構。由于網卡主控制器的內部差異,其他網卡在初始化、接收數據以及發送數據方面會有不同,但是在其他方面,PCI網卡END驅動程序都可以參考Rtl8139C網卡驅動程序的實現。
參考文獻:
[1]Tornado BSP Training Workshop. Version 1.0.2 . Wind River Systems, Inc. April 1998
[2]Tornado Device Driver Workshop.
[3]李貴山,陳金鵬. PCI局部總線及其應用[M]. 西安:西安電子科技大學出版社,2003.