對於那些想了解更多有關網卡如何工作、或如何使用現有驅動程序,以及試圖為目前不支持的網卡編寫自己的驅動程序的人來說,這些信息應該會有用。如果你沒有這種想法,那麼最好跳過這一節。 1可編程I/O、共享內存與DMA 如果已經可以發送接收背靠背數據包,就無
對於那些想了解更多有關網卡如何工作、或如何使用現有驅動程序,以及試圖為目前不支持的網卡編寫自己的驅動程序的人來說,這些信息應該會有用。如果你沒有這種想法,那麼最好跳過這一節。
1 可編程I/O、共享內存與DMA
如果已經可以發送接收背靠背數據包,就無法把更多的數據放到網絡上。每一個現代的以太網卡都可以接收背靠背數據包。Linux的DP8390驅動程序(wd80x3、SMC-Ultra、3c503、ne2000,等等)基本上都可以發送背靠背數據包(依賴於當前的中斷延遲),3c509和AT1500的硬件在自動發送背靠背數據包上沒有一點問題。
ISA總線可以達到5.3MB/sec (42Mb/sec),對10Mbps以太網而言已經足夠了。對於100Mbps網卡,顯然需要更快的總線來充分利用網絡帶寬。
可編程I/O(如NE2000、3c509)
優點:沒有使用任何受限制的系統資源,只用了若干I/O寄存器,而且沒有16M的限制。
缺點:一般傳輸速率較慢,CPU需要等待,幾乎不可能訪問交叉的數據包。
共享內存(如WD80x3、SMC-Ultra、3c503)
優點:簡單,比可編程I/O速度快,允許隨機訪問數據包。在可能的情況下,Linux驅動程序在從網卡復制出接收的IP數據包時計算其校驗和,從而比相應的PIO網卡進一步減少了對CPU的占用。
缺點:使用高端內存空間(對DOS用戶來說是個大問題,在Linux下沒有問題),依然要占用CPU。
從屬(普通)的直接內存存取(Linux下沒有這種情況!)
優點:在實際數據傳遞過程中不占用CPU。
缺點:檢查邊界條件、分配相鄰的緩存和DMA寄存器編程使該方法成為最慢的技術。它還占用了一個珍貴的DMA通道,並要求對齊的低端內存緩存。
總線控制的直接內存存取(如LANCE、DEC 21040)
優點:在數據傳輸過程中不占用CPU,可以把緩存串起來,CPU時間很少或不花費在ISA總線上。大多數總線控制的Linux驅動程序現在使用一種“copybreak”方案,較大的數據包直接從網卡放進內核的網絡緩存,小的數據包被CPU復制到cache裡進行下一步的處理。
缺點:(只適用於ISA總線的網卡)網卡要求低端內存緩存和一個DMA通道。任何總線控制器在與其它強占總線的總線控制器,如某些古老的SCSI適配器,一起工作時都會出問題。有幾個設計低劣的主板芯片組在與總線控制器一起使用時也有麻煩。不使用任何類型的DMA設備的一個原因是使用了設計為代替386的486處理器插件:這些處理器在每個DMA周期都必須刷新cache。(這其中包括Cx486DLC、Ti486DLC、Cx486SLC、Ti486SLC,等等。)
2 編寫驅動程序
在Linux下使用以太網卡所必需的只不過是相應的驅動程序。因此,關鍵是制造商要向公眾公開編程的技術資料,而無需你(或其他什麼人)簽署什麼協議。關於獲取資料的可能性(也許你不編寫代碼,那麼就是其他人編寫你確實需要的驅動程序的可能性),一個較好的指南是Crynwr (nee Clarkson)的包驅動程序的可用性。Russ Nelson在干這些事,對開發Linux驅動程序很有幫助。網上沖浪者可以試著看一下Russ的軟件。
Russ Nelson's Packet Drivers
有了資料,就可以為網卡編寫驅動程序並在Linux下使用(至少從理論上來說是這樣)。記住,有些為XT一類機器設計的老式硬件在Linux這樣的多任務環境下工作得不是很好。如果網絡流量較大,使用這些網卡會帶來大麻煩。
大多數網卡都帶有如NDIS和ODI一類的MS-DOS接口的驅動程序,但對Linux沒有用。許多人建議直接鏈接它們或自動翻譯一下,但這幾乎是不可能的。MS-DOS驅動程序需要在16比特模式,並依賴於“軟件中斷”,這二者與Linux內核不兼容。這種不兼容實際上是Linux的一個特性,有些Linux驅動程序比其相應的MS-DOS驅動程序要好得多。比如“8390”系列驅動程序使用乒乓傳送緩存,該方法剛剛被引進MS-DOS。
(乒乓傳送緩存意味著為傳送數據包使用至少兩個最大大小的包緩存。在網卡發送其中的一個時,載入另一個。在第一個包被發出去後,立刻發送第二個包,依次類推。這樣,大多數網卡就可以連續向線路上發送背靠背數據包。)
好啦。你可以決定為Foobar Ethe
.net網卡編寫驅動程序了,因為你有編程資料,而且還沒人寫這個驅動程序。(......這是兩個主要的
需求)你可以從Linux內核源碼樹中提供的網絡驅動程序框架開始。在所有近期的內核裡都能找到這個文件/usr/src/
linux/drivers/net/skeleton.c。也可以看看如下URL的Kernel Hackers Guide:KHG
3 內核的驅動程序接口
下面對編寫一個新驅動程序所必需的函數進行了若干說明。和上面提到的驅動程序框架一起閱讀可以更清楚一些。
探測
在啟動時調用以檢查網卡存在與否。如果可以通過讀取內存等非強制手段進行檢查最好。也可以從I/O端口讀取。在探測開始向I/O端口寫不好,因為這樣可能會損害另一個設備。通常在這裡還進行一些設備初始化(分配I/O空間、IRQ、填充dev->???域等等)。必須了解網卡可以配置到哪些I/O端口/內存、如何啟用共享內存(如果用了的話)以及如何選擇/啟用中斷產生,等等。
中斷處理程序
在網卡發出一個中斷時內核調用的程序。他需要確定網卡發出中斷的原因並進行相應的操作。一般的中斷條件是接收到數據、發送完成、報告出錯狀況。需要了解相關的中斷狀態位以進行相應的操作。
傳送函數
與dev->hard_start_xmit()鏈接,在內核想通過設備傳送數據時調用它。該函數把數據放入網卡並觸發傳送。需要了解如何把數據打包並傳給網卡(共享內存拷貝、PIO傳送、DMA?),以及放入網卡正確的位置。然後需要了解如何通知網卡把數據發送到線路上,(可能)在發送完成後發出一個中斷。在硬件無法接收更多數據包時需要設置dev->tbusy標志。在網卡有空間可用時,一般這發生在傳送完成中斷過程中,清除dev->tbusy標志並用mark_bh(INET_BH)通知上一層。
接收函數
在網卡報告有數據時由內核中斷處理程序調用。它把數據從網卡上移出,放入一個sk_buff並通過執行netif_rx(sk_buff)告訴內核數據所在位置。需要了解如何在接收數據時啟用中斷生成,如何檢查相關的接收狀態位,以及如何從網卡獲取數據(通過共享內存拷貝、PIO、DMA,等等)。
打開函數
與dev->open鏈接,在有人使用ifconfig eth0 up時網絡層調用它—— 把設備連到線路上並啟用來接收/發送數據。任何在探測過程中(啟用IRQ生成等)沒有完成的特別的初始化操作都在這裡進行。
關閉函數(可選)
在有人使用ifconfig eth0 down時使網卡進入一個清醒的狀態。如果硬件許可的話它會釋放中斷和DMA通道,並完全關閉以節約能源(象收發器一樣)。
其它函數
象一個重新設置函數,如果事情變得很糟,驅動程序可以試圖重新設置網卡作為最後防線。一般在發送超時或類似情況下如此進行。也是一個讀取網卡統計寄存器的函數,如果是這樣配備的話。
4 3Com的技術信息
如果對3Com網卡驅動程序的工作感興趣,可以從3Com公司獲取技術資料。Cameron友好地告訴了我們該如何做:
在我們的“技術參考文獻”裡給出了3Com的以太網適配器驅動程序
程序員需要了解的資料。這些手冊描述了板上的程序員接口,但沒有提及診斷、安裝程序等終端用戶所看到的東西。
網絡適配器分部的市場部有技術參考資料分發。為了使這個計劃更有效,我們把它集中到一個稱作“CardFacts”的自動電話系統裡。你可以打電話來,然後它把資料傳真給你。要索取技術參考資料,打電話到408-727-7021。索取開發人員的訂單,資料號是9070。在打電話前准備好你的傳真號碼。填完訂單後把它傳真到408-764-5004。手冊會由聯邦速遞的次日服務送到。
有人認為我們的手冊不該免費,他們也在尋找此系統過於昂貴或占用的時間和努力太多的證據。到目前為止,3Com的顧客確實很好,向我們提出的要求也很合理。我們需要你們的繼續合作並把這樣的服務維持下去。
5 基於AMD PCnet/LANCE的網卡的注意事項
AMD的LANCE(以太網的局域網控制器)是最早提供的,已經被“PCnet-ISA”芯片所取代,否則又名為79C960。注意,名稱“LANCE”有毛病,有些人會用老名稱稱呼新芯片。AMD的網絡產品分部的Dave Roberts友好地提供了下面有關該芯片的信息:
“從功能上來看,它等同與NE1500。它的寄存器組與使用附加1500/2100結構的老式LANCE一樣。PCnet-ISA可以使用較早的1500/2100驅動程序。NE1500和NE2100的結構基本上是相同的。開始Novell把它稱為2100,但後來想區分同軸電纜與10BASE-T網卡。屬於10BASE-T的就只采用1500范圍的編號。這是僅有的區別。
許多公司提供基於PCnet-ISA的產品,包括HP、Racal-Datacom、Allied Telesis、Boca Research、Kingston Technology等等。除了有些制造商增加了“無跳線”特性允許軟件配置網卡外,這些網卡基本上都是一樣的。大多數制造商沒有增加這一特性。AMD提供了一個使用PCnet-ISA的網卡的標准設計軟件包,許多制造商不加改變地直接使用我們的設計。這也就是說,如果想編寫大多數基於PCnet-ISA的網卡的驅動程序,只需要從AMD獲取數據資料。打電話給我們的資料分發中心(800)222-9323,索取PCnet-ISA的數據資料Am79C960。這是免費的。
要迅速了解一塊網卡是否“標准”網卡只需要看一下它。如果是標准的,網卡上只有一塊大的芯片、一塊晶振、一塊小的IEEE地址PROM、可能還有一個啟動ROM的插座和一個連接器(依照提供的媒介選項可能是1、2或3)。注意,如果是同軸電纜網卡,卡上就應該有一些收發器緩存,它們靠近連接器,遠離PCnet-ISA。”
一個可能的網卡黑客需要注意,不同的LANCE產品采用不同的“重起”方法。有些恢復到上次離開網絡環路的地方,另一些從環路的開頭開始,就象剛被初始化一樣。
6 廣播與混雜模式
Donald所做的另一件事是實現廣播與混雜模式的鉤子。所有發布的(即不是ALPHA的)ISA驅動程序現在都支持混雜模式。
Donald寫道:“我准備從討論混雜模式開始,它從概念上來說很容易實現。對大多數硬件,你只需要設置一個寄存器位,然後就可以接收到線路上的每一個數據包。對,差不多就這麼簡單;對有些硬件,你必須先關閉板卡(可能會丟失若干數據包),重新配置它,然後重新啟用以太網卡。對吧,就這麼簡單,下面要討論的就不是這麼明顯了:廣播模式。它可以用兩種方式實現:
使用混雜模式和一個如Berkeley包過濾器(BPF)的數據包過濾器。BPF是一個模式匹配指令語言,可以編寫一個程序挑出感興趣的地址。它的優點在於它很普遍和可編程。其缺點是沒有一個一般性的方法可以讓內核避免打開混雜模式和通過每一個注冊的包過濾器運行每一個線路上的數據包。參見Berkeley包過濾器以了解更多信息。
使用絕大多數以太網芯片內建的廣播包過濾器。
我想應該列出幾個以太網卡/芯片提供的廣播包過濾器:
芯片/網卡 混雜模式 廣播包過濾器
----------------------------------------
Seeq8001/3c501 Yes Binary filter (1)
3Com/3c509 Yes Binary filter (1)
8390 Yes Autodin II six bit hash (2) (3)
LANCE Yes Autodin II six bit hash (2) (3)
i82586 Yes Hidden Autodin II six bit hash (2) (4)
這些網卡聲稱有一個過濾器,但只是簡單地對“a
clearcase/" target="_blank" >ccept all multicast packets”或“accept no multicast packets”回答yes/no。
AUTODIN II是標准的以太網CRC校驗多項式。在這種方式下,廣播地址被哈希運算後在哈希表裡進行查找。如果啟用了相應的比特位,則數據包被接收。以太網數據包的設計使得硬件在如此處理時的開銷很小——(一般)只要在前6個八進制數(目標地址)之後鎖定CRC電路(用來進行錯誤檢查)的6個比特位,把它們作為哈希表的索引(6比特——一個64比特的表)。
這些芯片使用6比特哈希,必須由主機計算並載入哈希表。這也就是說內核必須包含CRC代碼。
82586內部使用6比特哈希,但是由自己從接受的廣播地址列表計算出哈希表。
注意,這些芯片的過濾效果都不好,還需要一個中間層次的模塊完成最後的過濾。同時還要注意,在每種情況下都必須保持一個完整的接受廣播地址列表,在出現變化時以重新計算哈希表。
7 Berkeley包過濾器(BPF)
開發者普遍認為BPF的功能不該由內核提供,而是放在一個(但願很少使用的)兼容庫裡。
對不了解的人來說:BPF(Berkeley包過濾器)是一種向內核網絡層說明對哪些數據包感興趣的機制。它是用一種建立在底層網絡代碼中的特殊指令語言解釋器實現的。應用程序把一個用這種語言編寫的程序傳遞給內核,然後內核對每一個接收到的數據包執行該程序。如果內核有多個BPF應用程序,對每個數據包都要運行這幾個程序。
問題在於很難從數據包過濾器程序推斷出應用程序實際上對哪一種數據包感興趣,所以一般的解決方法就是始終運行過濾器。假設一個應用程序注冊的BPF程序是獲取發往某個廣播地址的低速數據流。絕大多數以太網卡有一個64個入口的哈希表的硬件實現的廣播地址過濾器,用來忽略大多數不想要的廣播數據包,所以有可能以極低的開銷完成這一操作。但是由於有了BPF,內核必須把接口設置為混雜模式,接收所有數據包,並對它們運行過濾器。不管怎樣,這樣確實可以工作,但考慮到對所要求的數據包進行的處理,就已經變得過於麻煩了。
--------------------------------------------------------------------------------
關於Linux下網卡的一些技術信息(續)
所有不適合放在別處的相關信息都堆在這裡。可能不相干,也可能大家不感興趣,但還是放在這兒了。
1 向內核傳遞以太網參數
有兩個通用的內核命令可以在啟動時向內核傳遞以太網參數(ether和reserve)。可以用LILO、loadlin或其它接受可選參數的啟動工具完成該操作。
例如,如果命令為“blah”,希望接收3個參數(假定為123、456和789),那麼在使用LILO時就應該如下:
LILO: linux blah=123,456,789
要了解啟動時參數的更多信息(和完全的列表),請參見BootPrompt-HOWTO
ether命令
ether=參數與直接構建在內核的驅動程序一起使用。ether=參數對一個模塊化的驅動程序完全不起作用。它的最通用形式如下:
ether=IRQ,BASE_ADDR,PARAM_1,PARAM_2,NAME
所有的參數都是可選的。第一個非數字的參數被用做NAME。
IRQ: 很明顯。為“0”的IRQ值(一般為缺省值)意味著autoIRQ。首先設置IRQ而不是base_addr是一個歷史性的巧合——無論改變別的什麼時都可以改正這一點。
BASE_ADDR: 也很明顯。值為“0”(一般為缺省值)意味著探測以太網卡的網卡類型特定的地址列表。
PARAM_1: 這開始是用來覆蓋WD80*3這樣的共享內存網卡的起始內存的值。有些驅動程序使用該值的低4位來設置診斷信息級別。0 -- 缺省值,1-7 -- 級別1..7,(7是最完全的信息)8 -- 級別0(沒有信息)。另外,LANCE驅動程序使用該值的低4位來選擇DMA通道。否則就使用auto-DMA。
PARAM_2: 3c503驅動程序使用它來選擇內部還是外部收發器。0 -- 缺省/內部, 1 -- 外部AUI。Cabletron的E21XX網卡還使用PARAM_2的低4位來選擇輸出媒介。否則就自動檢測。
NAME: 選擇該值所指的網絡設備。標准內核對附屬於總線的以太網卡使用名稱“eth0”、“eth1”、“eth2”和“eth3”,對並口“袖珍”以太網適配器使用“atp0”。arcnet驅動程序使用名稱“arc0”。可以使用這些LILO參數明確設置基址來啟用多塊網卡。1.0內核把基於LANCE的以太網卡作為特殊情況進行處理:LILO參數被忽略,LANCE網卡總是被分配為從“eth0”開始的名稱“eth”。附加的非LANCE網卡必須被明確指定為“eth”,並用諸如“ether=0,-1,eth0”的方式禁止通常的“eth0”探測。(對,這是個
Bug。)
reserve命令
這個緊接著的LILO命令用法與上面的“ether=”一樣,即附加在lilo.conf裡指定的啟動選擇名稱後面。
reserve=IO-base,extent{,IO-base,extent...}
在某些機器上,可能需要防止設備驅動程序在某個特定區域裡檢查設備(自動探測)。其原因可能是由於設計低劣的硬件使啟動凝結(如某些以太網卡)、被錯誤識別的硬件、在較早的探測中狀態被改變的硬件、或者僅僅是不想讓內核初始化硬件。
啟動時的參數reserve通過指定無需探測的I/O端口區域來解決這個問題。該區域保留在內核的端口注冊表裡,就象該區域裡已經發現了一個設備一樣。注意,這一機制在大多數機器上是不必要的。只有在有問題或特定的情況下才有必要使用它。
指定區域裡的I/O端口受到保護,不被設備探測影響。在某些驅動程序被NE2000掛起,或其它設備被錯誤地識別為NE2000時使用這一方法。正確的設備驅動程序不該探測一個保留區域,除非另一個啟動參數明確指定它這麼做。這隱含了reserve經常與其它啟動參數一起使用。因此,如果指定了一個reserve區域來保護某個特定設備,通常就必須明確指定對該設備的探測。大多數驅動程序在給定了明確地址後就忽略了端口注冊表。
例如,啟動行
LILO: linux reserve=0x300,32 ether=0,0x300,eth0
使以太網卡驅動程序以外的所有設備驅動程序都不探測0x300-0x31f。
一般啟動時的參數限制是11個,因此每個reserve關鍵詞只能指定5個保留區域。如果請求很復雜,可以使用多個reserve指令。
2 把以太網驅動程序作為模塊使用
現在大多數Linux發行版裡的內核都只包含很少幾個內建的驅動程序。驅動程序都采用獨立的動態可加載模塊的形式提供。這些模塊化驅動程序通常由管理員使用modprobe(8)命令載入,或者在某些情況下由內核通過“kerneld”(在2.0版)或“kmod”(在2.1版)自動載入,然後調用modprobe。
你所用的發行版可能會提供良好的圖形配置工具來設置以太網模塊。如果可能就先使用它們。下面描述了在這些花俏的配置程序下的信息,以及這些程序改變了哪些東西。
控制使用哪些模塊和每個模塊提供哪些選項的信息一般保存在文件/etc/conf.modules裡。在這個文件裡使用的兩個感興趣的主要選項(對以太網卡而言)是alias和options。modprobe命令查閱該文件以了解模塊信息。
實際的模塊本身一般保存在名為/lib/modules/`uname -r`/net的目錄下,其中uname -r命令給出內核的版本(如2.0.34)。你可以在這裡看看哪一個模塊與你的網卡匹配。
在你的conf.modules文件裡首先需要的是告訴modprobe對於eth0(和eth1以及......)網絡接口使用什麼驅動程序。為此要使用alias命令。例如,有一塊使用smc-ultra.o驅動程序模塊的ISA SMC EtherEZ網卡,需要增加如下一行把該驅動程序alias到eth0上:
alias eth0 smc-ultra
其次,可能需要一個options行來指出與某個特定模塊(或模塊別名)一起使用哪些選項。還采用上面那個例子,如果只有一行alias而沒有options行,內核會警告(參見dmesg)說自動探測ISA網卡不好。要消除這個警告,需要增加另一行來告訴模塊網卡被配置在哪個I/O基址上,比方說是16進制地址0x280。
options smc-ultra io=0x280
大多數ISA模塊在insmod命令行接受io=0x340和irq=12這樣的參數。提供這些參數以避免探測該網卡是必須的或至少是強烈建議的。與PCI和EISA設備不同,對大多數ISA設備而言沒有真正
安全的自動探測方法,所以在把驅動程序作為模塊使用時應當避免自動探測。
每個模塊所接受的所有選項列表可以在以下文件中找到:
/usr/src/linux/Documentation/networking/net-modules.txt
推薦閱讀該文件以了解對你的特定網卡可以使用哪些選項。注意,對於單個模塊能夠處理多個設備的模塊,有些支持用逗號分開的值列表,如所有基於8390的驅動程序和PLIP驅動程序。例如:
--------------------------------------------------------------------------------
options 3c503 io=0x280,0x300,0x330,0x350 xcvr=0,1,0,1
--------------------------------------------------------------------------------
上面就是一個模塊控制四塊3c503網卡,其中網卡2和4使用外部收發器。不要在“=”或逗號周圍使用空格。
還要注意,一個忙的模塊不能被刪除。這也就是說在刪除模塊前需要使用ifconfig eth0 down(關閉以太網卡)。
命令lsmod可以顯示哪些模塊被載入、它們是否正在被使用,而rmmod可以刪除這些模塊。