LinuxE1000網(wǎng)卡驅(qū)動分析_第1頁
LinuxE1000網(wǎng)卡驅(qū)動分析_第2頁
LinuxE1000網(wǎng)卡驅(qū)動分析_第3頁
LinuxE1000網(wǎng)卡驅(qū)動分析_第4頁
LinuxE1000網(wǎng)卡驅(qū)動分析_第5頁
免費預(yù)覽已結(jié)束,剩余4頁可下載查看

付費下載

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

1、Linux-千兆網(wǎng)卡驅(qū)動實現(xiàn)機制淺析作者:Minit,出處:博客,責(zé)任編輯:羅麗艷,2009-03-2900:00網(wǎng)卡作為一個PCI設(shè)備,其必須遵守相應(yīng)的PCI規(guī)范,即必須為網(wǎng)卡定義相應(yīng)的標(biāo)識號,每個PCI外設(shè)由一個總線編號、一個設(shè)備編號及一個功能編號來標(biāo)識。網(wǎng)卡驅(qū)動程序則需要定義相應(yīng)的pci_device_id結(jié)構(gòu)來表示其支持的PCI外設(shè)的標(biāo)識1 .引言本分析主要針對e1000網(wǎng)卡,驅(qū)動源碼為7.3.20-k2。本文的目的不是為了講述如何編寫驅(qū)動程序,主要是分析網(wǎng)卡驅(qū)動內(nèi)部的實現(xiàn)機制。通過此分析,希望可以理解驅(qū)動程序中的各個部分的關(guān)系,對網(wǎng)卡發(fā)送和接收數(shù)據(jù)包有直觀的了解,同時也希望對設(shè)計網(wǎng)卡

2、驅(qū)動程序有幫助。由于網(wǎng)卡驅(qū)動程序與硬件和操作系統(tǒng)都有很緊密的聯(lián)系,故要把某些問題完全弄清楚,需要很多的經(jīng)驗與相關(guān)知識,介于自身的水平有限,且自身經(jīng)驗較少,故肯定存在很多問題,希望本文的讀者發(fā)現(xiàn)了問題不吝與作者聯(lián)系。2 .網(wǎng)卡驅(qū)動的體系結(jié)構(gòu)網(wǎng)卡作為一個PCI設(shè)備,其必須遵守相應(yīng)的PCI規(guī)范,即必須為網(wǎng)卡定義相應(yīng)的標(biāo)識號,每個PCI外設(shè)由一個總線編號、一個設(shè)備編號及一個功能編號來標(biāo)識。網(wǎng)卡驅(qū)動程序則需要定義相應(yīng)的pci_device_id結(jié)構(gòu)來表示其支持的PCI外設(shè)的標(biāo)識,通過在驅(qū)動程序的pci_device_id中查找設(shè)備標(biāo)識號,將驅(qū)動程序與設(shè)備聯(lián)系起來。網(wǎng)卡作為PCI設(shè)備,其包括兩類空間,一種

3、是配置空間,CPU不能直接訪問,訪問這個空間,需要借助BIOS功能;另一種是普通的控制寄存器空間,這部分經(jīng)過映射后,CPU可以直接訪問控制。在硬件加電初始化時,BIOS統(tǒng)一檢查所有的PCI設(shè)備,并為每個設(shè)備分配一個物理地址,該地址通過BIOS獲得并寫到設(shè)備的配置空間內(nèi),驅(qū)動程序就可以將網(wǎng)卡的普通控制寄存器映射到一段內(nèi)存空間內(nèi),CPU通過訪問映射后的虛擬地址來操控網(wǎng)卡的寄存器。當(dāng)操作系統(tǒng)初始化日其為每個PCI設(shè)備分配一個pci_dev結(jié)構(gòu),并將前面分配的物理地址寫到pci_dev的resource字段中。在網(wǎng)卡驅(qū)動程序中則可以通過讀取pci_dev中的resource字段獲得網(wǎng)卡的寄存器配置空間

4、地址,其由函數(shù)pci_resource_start。和pci_resource_end()獲得該空間的起始位置,通過ioremapO將該段位置映射到主存中,以便CPU訪問控制網(wǎng)卡的I/O和內(nèi)存空間。如重啟網(wǎng)卡設(shè)備,則是通過向映射后的網(wǎng)卡的相應(yīng)寄存器寫入命令實現(xiàn),其通過映射后的首地址及相應(yīng)的寄存器偏移量找到該寄存器的位置,然后通過函數(shù)writebO寫該寄存器。有關(guān)相關(guān)寄存器對應(yīng)的偏移量,一般是通過網(wǎng)卡的相關(guān)的datasheet獲得。如果要獲取網(wǎng)卡的MAC地址,則一般通過函數(shù)readbO讀取首地址開始的前六位內(nèi)容即可得至必通過pci_read_config_和pci_write_config_系列

5、函數(shù)可以讀寫網(wǎng)卡的配置空間,如開啟網(wǎng)卡設(shè)備就是將網(wǎng)卡配置空間的command域置1,從而設(shè)備就可以將寄存器映射到內(nèi)存。如通過函數(shù)pci_read_config_byte(pci_devpdev,PCI_INTERRUPT_LINE,&irq)獲得設(shè)備所分配的中斷號并保存在irq中。pci_read_config_和pci_write_config_系列函數(shù)實際上是調(diào)用pci_bus_read_config_和pci_bus_write_config_系列函數(shù)實現(xiàn)的,這些函數(shù)實際操作網(wǎng)卡對應(yīng)的PCI總線結(jié)構(gòu)。有關(guān)PCI寄存器的配置空間可參考LinuxDeviceDriver3rd或PCI

6、BusDemystified»0網(wǎng)卡作為一個規(guī)范的pci設(shè)備,其對應(yīng)的結(jié)構(gòu)體pci_dev代表了網(wǎng)卡設(shè)備,體現(xiàn)了作為PCI設(shè)備所應(yīng)有的規(guī)范。網(wǎng)卡的網(wǎng)絡(luò)傳輸性質(zhì),實際是通過另一結(jié)構(gòu)體net_device來體現(xiàn)的,該結(jié)構(gòu)體的初始化由網(wǎng)卡驅(qū)動程序?qū)崿F(xiàn)。內(nèi)核中對網(wǎng)卡的操作,其實質(zhì)就是對net_device結(jié)構(gòu)的操作,pci_dev和net_device都表示網(wǎng)卡設(shè)備,只是體現(xiàn)的角度不一樣。net_device是對特定適配器的抽象,其為上層協(xié)議提供了統(tǒng)一的接口,網(wǎng)卡驅(qū)動則基于特定適配器實現(xiàn)了這一抽象。PCI設(shè)備的驅(qū)動程序由pci_driver結(jié)構(gòu)體表示,故網(wǎng)卡驅(qū)動應(yīng)該是該結(jié)構(gòu)體的一個實例,在該

7、結(jié)構(gòu)體中應(yīng)該要定義實現(xiàn)與網(wǎng)卡相關(guān)的參數(shù)以及相應(yīng)的操作。網(wǎng)卡驅(qū)動實際操作的特定適配器,是由與硬件相關(guān)的adapter所表示的2構(gòu)體,adapter體現(xiàn)了大部分與硬件相關(guān)的屬性,網(wǎng)卡驅(qū)動除了直接對pci_dev結(jié)構(gòu)操作外,其他對網(wǎng)卡設(shè)備的操作基本是對adapter結(jié)構(gòu)體的操作。adapter體現(xiàn)了net_device與pci_dev的關(guān)聯(lián),也實現(xiàn)了網(wǎng)絡(luò)設(shè)備的適配器無關(guān)性。與網(wǎng)卡設(shè)備pci_dev的通信是通過adapter來實現(xiàn)的,而這個實現(xiàn)則是網(wǎng)卡驅(qū)動所要完成的任務(wù)。下面圖2-1描述了三個重要數(shù)據(jù)結(jié)構(gòu)間的關(guān)系,pci_dev結(jié)構(gòu)體現(xiàn)了網(wǎng)卡的配置空間和I/O與內(nèi)存區(qū)域,net_device結(jié)構(gòu)則向內(nèi)

8、核提供了操作網(wǎng)卡的抽象接口,其參數(shù)值可按照功能分為5個部分。e1000_adapter結(jié)構(gòu)除了體現(xiàn)相應(yīng)的硬件無關(guān)性外,還管理了發(fā)送與接收數(shù)據(jù)包的相應(yīng)緩沖空間,網(wǎng)卡的物理地址空間映射后的虛擬地址也在此結(jié)構(gòu)中保存。e1000_adapter結(jié)構(gòu)中的e1000_hw結(jié)構(gòu)主要保存網(wǎng)卡的硬件參數(shù),其值就是通過讀取pci_dev的內(nèi)容獲取而來的。以上的數(shù)據(jù)結(jié)構(gòu)在網(wǎng)卡工作時起著最核心的作用,同時也是編寫驅(qū)動程序必須操作的結(jié)構(gòu)體oRataontheNetworkLayerDevice-DriverMethodsGeneralFie1dsofaNetworkDeviceDatannchePhysicalLaye

9、rarcci!icFieldsnet_deviceel000adapterel000hw(力rdigura1innSpaceI/OandMemorypci_dev圖2-1網(wǎng)卡驅(qū)動程序的主要數(shù)據(jù)結(jié)構(gòu)3 .網(wǎng)卡設(shè)備的注冊與初始化網(wǎng)卡設(shè)備的注冊與初始化是在其相關(guān)的驅(qū)動程序的el000_probe()函數(shù)中實現(xiàn)的,有關(guān)設(shè)備如何與該驅(qū)動相關(guān)聯(lián),以及如何調(diào)用到e1000_probe()的,在此不作介在函數(shù)e1000_probe()中首先調(diào)用函數(shù)pci_enable_device()啟用設(shè)備,然后聲明了DMA空間,接著調(diào)用函數(shù)alloc_etherdev()生成結(jié)構(gòu)體net_device,該結(jié)構(gòu)體就表示了網(wǎng)

10、卡設(shè)備,對net_device的參數(shù)進(jìn)行了初始化后,調(diào)用register_netdev()注冊該設(shè)備。以上僅是對設(shè)備的注冊,設(shè)備的初始化主要包括對兩個結(jié)構(gòu)體的賦值,一個是net_device,另一個則是e1000_adapter。對e1000_adapter的初始化包括對其中的e1000_hw結(jié)構(gòu)的初始化,其調(diào)用函數(shù)e1000_sw_init()實現(xiàn)。在又te1000_hw的初始化過程中使用了ioremap()實現(xiàn)了網(wǎng)卡硬件地址與內(nèi)存虛擬地址之間的映射。對網(wǎng)卡設(shè)備進(jìn)行撤銷則調(diào)用函數(shù)free_netdev()實現(xiàn)。有關(guān)網(wǎng)卡設(shè)備注冊與初始化的更詳細(xì)的過程可以參考UnderstandingLinux

11、NetworkInternals»。4 .網(wǎng)卡設(shè)備的啟動與關(guān)閉網(wǎng)卡設(shè)備啟動時首先調(diào)用函數(shù)el000_open(),在該函數(shù)中調(diào)用el000_request_irq()申請中斷號及其相應(yīng)的中斷處理程序e1000_intr(),其實際是調(diào)用request_irq()函數(shù)來實現(xiàn)的。在函數(shù)el000_open()中調(diào)用e1000_setup_all_tx_resources()根據(jù)發(fā)送隊列數(shù)建立發(fā)送緩沖區(qū),每個緩沖區(qū)的建立由函數(shù)el000_setup_tx_resources()實現(xiàn),在e1000_setup_tx_resources()中,主要是對描述發(fā)送緩沖區(qū)的結(jié)構(gòu)體el000_tx_r

12、ing的初始化,其將DMA緩沖區(qū)與網(wǎng)卡所映射的虛擬地址空間聯(lián)系起來,使用函數(shù)pci_alloc_consistent()實現(xiàn)一致性映射。而虛擬地址空間與網(wǎng)卡的物理地址相對應(yīng),故而這三種空間就對應(yīng)了起來,DMA也就可以在此基礎(chǔ)上實現(xiàn)了,當(dāng)數(shù)據(jù)包內(nèi)容被映射到DMA緩沖區(qū)后,其將完全由設(shè)備操控。DMA的緩沖區(qū)的初始化在驅(qū)動程序的e1000_probe()函數(shù)中實現(xiàn)。e1000_open()函數(shù)會調(diào)用e1000_up()對網(wǎng)卡的一些相關(guān)的軟硬件參數(shù)與空間進(jìn)行配置,如硬件寄存器的讀寫,數(shù)據(jù)包接收與發(fā)送空間的處理函數(shù)的初始化等。發(fā)送緩沖空間的初始化結(jié)構(gòu)及相互間的關(guān)系如圖4-1所示。接收緩沖區(qū)的初始化與上述

13、類似,由e1000_setup_all_rx_resources()調(diào)用e1000_setup_rx_resources()對結(jié)構(gòu)體e1000_rx_ring進(jìn)行初始化。接收緩沖空間的結(jié)構(gòu)如圖4-2所示番15L翻Ster-t'l此*Ke>F圖4-2接收緩沖區(qū)的結(jié)構(gòu)圖網(wǎng)卡的關(guān)閉由函數(shù)e1000_close()實現(xiàn),其會首先關(guān)閉中斷,然后釋放中斷號,并且會釋放網(wǎng)卡申請的相應(yīng)的空間5.發(fā)送與接收數(shù)據(jù)包數(shù)據(jù)包的發(fā)送:.1必_士旭erMl加懺Virtual圖5-1發(fā)送數(shù)據(jù)包的結(jié)構(gòu)圖及相互關(guān)系根據(jù)發(fā)送隊列數(shù)num_tx_queues建立相應(yīng)的發(fā)送緩沖區(qū)結(jié)構(gòu)e1000_tx_ring,在該結(jié)構(gòu)

14、中有描述該區(qū)域的指向e1000_tx_desc結(jié)構(gòu)的desc,該緩沖區(qū)指向的dma總線地址,用于接收硬件傳送來的用el000_buffer結(jié)構(gòu)描述的緩沖塊數(shù)組buffer_info,另外的幾個參數(shù)則主要用于描述這些緩沖塊,其中count表示緩沖塊的個數(shù),next_to_use和next_to_clean主要描述緩沖塊的使用狀態(tài),如已經(jīng)接收接收了數(shù)據(jù)的位置及準(zhǔn)備接收的位置,當(dāng)有新的數(shù)據(jù)包要發(fā)送時,首先由上層協(xié)議調(diào)用e1000_xmit_frame(),在該函數(shù)中接著調(diào)用e1000_tx_queue()根據(jù)相應(yīng)的參數(shù)找到緩沖塊存放,緩沖塊的初始化則由函數(shù)e1000_tx_map()實現(xiàn)。buffe

15、r_info指向的環(huán)形緩沖塊區(qū)域主要用來接收總線地址映射來的數(shù)據(jù)包,所有的緩沖塊用next_to_match連接成一個環(huán),每個緩沖塊用結(jié)構(gòu)體e1000_buffer表示,在該結(jié)構(gòu)中,skb存放數(shù)據(jù)包的內(nèi)容,dma表示該數(shù)據(jù)包所在的總線地址。此處使用函數(shù)pci_map_single()進(jìn)行流式映射,的映射方向為PCI_DMA_TODEVICE,控制總線會把虛擬地址空間所指內(nèi)容映射到總線地址,然后將該內(nèi)容由網(wǎng)卡傳送出去。發(fā)送數(shù)據(jù)包的相關(guān)結(jié)構(gòu)圖及相互關(guān)系如圖5-1所示。e1000_tx_ring結(jié)構(gòu)中的desc所指向的buffer_addr記錄了每次發(fā)送的緩沖塊所映射的總線地址,即buffer_ad

16、dr記錄的是總線地址o而desc本是一個虛擬地址,該虛擬地址是通過pci_alloc_consistent()映射的發(fā)送緩沖區(qū)的地址,其與DMA緩沖區(qū)中的一段總線地址相對應(yīng),該總線地址由el000_tx_ring結(jié)構(gòu)中的dma成員保存,這種映射關(guān)系在對開啟網(wǎng)卡時就實現(xiàn)了,其與在發(fā)送數(shù)據(jù)包時映射的總線地址有區(qū)別,后者是在發(fā)送時動態(tài)進(jìn)行的數(shù)據(jù)包的接收圖5-2接收數(shù)據(jù)包的結(jié)構(gòu)圖及相互關(guān)系根據(jù)接收隊列數(shù)num_rx_queues建立相應(yīng)的接收緩沖區(qū)結(jié)構(gòu)el000_rx_ring,在該結(jié)構(gòu)中有描述該區(qū)域的指向e1000_rx_desc結(jié)構(gòu)的desc,該緩沖區(qū)指向的dma總線地址,用于接收硬件傳送來的用e

17、1000_buffer結(jié)構(gòu)描述的緩沖塊數(shù)組buffer_info,另外的幾個參數(shù)則主要用于描述這些緩沖塊,其中count表示緩沖塊的個數(shù),next_to_use和next_to_clean主要描述緩沖塊的使用狀態(tài),如已經(jīng)接收接收了數(shù)據(jù)的位置及準(zhǔn)備接收的位置,當(dāng)有新的數(shù)據(jù)包要到來時,則根據(jù)這兩個參數(shù)找到相應(yīng)的區(qū)域存放。對于需要分片接收的數(shù)據(jù)包則利用了ps_page和ps_page_dma來實現(xiàn),參數(shù)cpu指定了該接收緩沖隊列所屬的處理器??偩€地址與要發(fā)送的虛擬地址間的映射方向為PCI_DMA_FROMDEVICE,控制總線會把總線地址的內(nèi)容映射到虛擬地址空間內(nèi)。接收數(shù)據(jù)包的相關(guān)結(jié)構(gòu)圖及相互關(guān)系如

18、圖5-2所示。buffer_info中找到一個當(dāng)有新的數(shù)據(jù)包到達(dá)時,首先觸動中斷處理函數(shù)e1000_intr(),在函數(shù)中會為新來的數(shù)據(jù)包在緩沖塊數(shù)組新的緩沖塊位置,并完成e1000_buffer結(jié)構(gòu)的賦值。數(shù)據(jù)包的接收其實就是將總線地址指向的內(nèi)容拷貝到skb中,然后根據(jù)skb中的協(xié)議將其傳給相應(yīng)的上層協(xié)議的接收函數(shù)。6 .網(wǎng)卡驅(qū)動程序的設(shè)計編寫網(wǎng)卡驅(qū)動程序,需要對以下三類結(jié)構(gòu)體進(jìn)行相應(yīng)的操作:1 .與網(wǎng)絡(luò)協(xié)議棧相關(guān)的結(jié)構(gòu)體,如sk_buff結(jié)構(gòu)體。2 .網(wǎng)卡和協(xié)議棧接口相關(guān)的結(jié)構(gòu)體,如net_device結(jié)構(gòu)體。3 .與I/O總線相關(guān)的結(jié)構(gòu)體,如利用PCI總線進(jìn)行數(shù)據(jù)包傳送的DMA緩沖區(qū)以及表示網(wǎng)卡的pci_dev結(jié)構(gòu)體。設(shè)計網(wǎng)卡驅(qū)動時,需要針對以上的數(shù)據(jù)結(jié)構(gòu)實現(xiàn)相應(yīng)的功能,如對sk_buff結(jié)構(gòu)的操作實現(xiàn)對數(shù)據(jù)包的有效控制;對net_device結(jié)構(gòu)的操作可以對網(wǎng)卡進(jìn)行操作(如開啟、關(guān)閉等)

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論