摘 要: 主要研究了基于Linux內(nèi)核的網(wǎng)卡驅(qū)動的移植。Linux網(wǎng)絡(luò)設(shè)備驅(qū)動程序的體系結(jié)構(gòu)可以分為4層,首先分析了各層的具體功能實現(xiàn),并在此基礎(chǔ)上充分利用S3C2440開發(fā)板完成DM9000網(wǎng)卡驅(qū)動的移植,編譯內(nèi)核生成內(nèi)核鏡像。最后介紹了網(wǎng)絡(luò)驅(qū)動測試的三種方法,并采用第一種方法,即使用ifconfig進行IP地址的設(shè)置,完成了測試。
關(guān)鍵詞: Linux內(nèi)核;網(wǎng)卡驅(qū)動;S3C2440;DM9000
0 引言
以太網(wǎng)(Ethernet)是一種計算機局域網(wǎng)組網(wǎng)技術(shù)。在局域網(wǎng)中,多個節(jié)點是共享傳輸介質(zhì)的,這就必須由某種機制來決定某個時刻哪個設(shè)備占用傳輸介質(zhì)來傳輸數(shù)據(jù),因此,局域網(wǎng)的鏈路層要有介質(zhì)訪問控制的功能,即數(shù)據(jù)鏈路層分為邏輯鏈路控制LLC子層和介質(zhì)訪問控制MAC子層[1]。
本文主要研究基于S3C2440的DM9000網(wǎng)卡驅(qū)動的移植。網(wǎng)絡(luò)對于嵌入式系統(tǒng)來說是必不可少的,但是S3C2440沒有集成以太網(wǎng)接口,所以要想使S3C2440具備以太網(wǎng)的功能,就必須擴展網(wǎng)卡接口。本文選擇外接DM9000,使其可以與以太網(wǎng)相連接,并完成DM9000網(wǎng)卡驅(qū)動的移植。
1 Linux網(wǎng)絡(luò)驅(qū)動層次
Linux網(wǎng)絡(luò)驅(qū)動可以劃分為4層,即網(wǎng)絡(luò)協(xié)議接口層、網(wǎng)絡(luò)設(shè)備接口層、設(shè)備驅(qū)動功能層和設(shè)備物理媒介層,內(nèi)核中是通過以dev_base為頭指針的設(shè)備鏈表來管理所有的網(wǎng)絡(luò)設(shè)備的。網(wǎng)絡(luò)設(shè)備驅(qū)動的編寫主要是網(wǎng)絡(luò)設(shè)備net_device的初始化和數(shù)據(jù)包的收發(fā)函數(shù)[2]。
網(wǎng)絡(luò)協(xié)議接口層最主要的功能是給上層協(xié)議提供透明的數(shù)據(jù)包發(fā)送和接收接口,當上層的API或IP需要發(fā)送數(shù)據(jù)包時,它將調(diào)用網(wǎng)絡(luò)協(xié)議接口層的dev_queue_xmit函數(shù)發(fā)送一個內(nèi)容為sk_buff的數(shù)據(jù);當上層需要接收數(shù)據(jù)時,則是通過向netif_rx函數(shù)傳遞一個sk_buff數(shù)據(jù)結(jié)構(gòu)的指針來完成的[3]。
網(wǎng)絡(luò)設(shè)備接口層主要是為變化多端的網(wǎng)絡(luò)定義了一個統(tǒng)一且抽象的net_device,實現(xiàn)了多種硬件在軟件層次上的統(tǒng)一。網(wǎng)絡(luò)設(shè)備驅(qū)動主要是填充net_device的成員并注冊net_device來實現(xiàn)硬件操作函數(shù)和內(nèi)核的掛接。通常情況下,網(wǎng)絡(luò)設(shè)備驅(qū)動以中斷方式接收數(shù)據(jù),而net_device中則定義了poll_controller這種純輪詢的接口方式,以提高Linux在寬帶系統(tǒng)上的性能。
設(shè)備驅(qū)動功能層中對于具體的設(shè)備,工程師應(yīng)該實現(xiàn)net_device中的open、stop、tx、hard_header、get_stats、tx_timeout、interruppt等函數(shù)。
網(wǎng)絡(luò)設(shè)備媒介層直接對應(yīng)實際的硬件設(shè)備,需要定義一組讀寫設(shè)備內(nèi)部寄存器的函數(shù),如ior、iow[4]。
2 網(wǎng)絡(luò)設(shè)備驅(qū)動移植
2.1 基于S3C2440的DM9000網(wǎng)卡驅(qū)動的移植
首先看內(nèi)核DM9000代碼,在/driver/net/Makefile查看:
obj-$(CONFIG_DM9000)+=dm9000.o
在/driver/net/Kconfig查看:
menuconfig NET_ETHERNET
bool "Ethernet (10 or 100Mbit)"
config DM9000
tristate "DM9000 support"
depends on ARM||BLACKFIN||MIPS
select CRC32
select MII
所以配置內(nèi)核make menuconfig時,需要選中這一項。
根據(jù)開發(fā)板電路圖知道,DM9000的AEN端口接到了nGCS4上,INT端口接到了IRQ_EINT7上,CMD端口接到了LADDR2上,數(shù)據(jù)線是SD0~SD15,即數(shù)據(jù)線的位數(shù)是16 bit。
根據(jù)S3C2440地址空間的分配與片選信號的定義知道,引腳nGCS4對應(yīng)的空間的起始地址為0x20000000,這由系統(tǒng)地址線控制。同時,DM9000使用的中斷號是IRQ_EINT7。另外,DM9000上的CMD信號用來控制是地址端口還是數(shù)據(jù)端口,如果CMD為0,即LADDR2為0,表示訪問地址寄存器;當CMD為1,即LADDR2為1,表示訪問數(shù)據(jù)寄存器[5]。
2.2 DM9000驅(qū)動的移植
在mach-S3C2440.c中添加如下代碼:
#include<linux/dm9000.h>
#define MACH_S3C2440_DM9K_BASE(S3C2410_CS4+0x300)
Static struct resource S3C2440_dm9k_resource[]={
[0]={//地址端口
.start=MACH_S3C2440_DM9K_BASE,
.end=MACH_S3C2440_DM9K_BASE+3,
.flags=IORESOURCE_MEM
},
[1]={//數(shù)據(jù)端口
.start=MACH_S3C2440_DM9K_BASE+4,
.end=MACH_S3C2440_DM9K_BASE+7,
.flags=IORESOURCE_MEM
},
[2]={//中斷號
.start=IRQ_EINT7,
.end=IRQ_EINT7,
.flags=IORESOURCE_IRQ|IORESOURCE_IRQ_HIGHEDGE,
//高電平觸發(fā)
}
};
Static struct dm9000_plat_data S3C2440_dm9k_pdata={
//數(shù)據(jù)線的位數(shù)是16 bit,沒有使用E2PROM
.flags=(DM9000_PLATF_16BITONLY|DM9000_PLATF_NO_ EEPROM),
.dev_addr={0x08,0x90,0x90,0x90,0x90,0x90},
//MAC地址
};
static struct platform_device S3C2440_device_eth={
.name="dm9000",//設(shè)備名
.id=-1,
.num_resources=ARRAY_SIZE(S3C2440_dm9k_resource),
.resource=S3C2440_dm9k_resource,//資源
.dev={
.platform_data=&S3C2440_dm9k_pdata,
//私有數(shù)據(jù)
},
};
最后在S3C2440的BSP文件mach-S3C2440.c中添加如下代碼:
static struct platform_device*S3C2440_devices[]__initdata={
……
& S3C2440_device_eth,//添加
};
移植完畢后編譯內(nèi)核生成內(nèi)核鏡像。
3 網(wǎng)絡(luò)設(shè)備驅(qū)動測試
網(wǎng)絡(luò)設(shè)備沒有字符設(shè)備里的open、close等函數(shù),而是靠IP地址選擇路由,Linux網(wǎng)絡(luò)系統(tǒng)的路由選擇會自動查找匹配合適的驅(qū)動,這是網(wǎng)絡(luò)驅(qū)動與其他兩種驅(qū)動的主要區(qū)別[6]。
下面給出三種測試網(wǎng)絡(luò)驅(qū)動是否正常的方法。
?。?)使用ifconfig進行IP地址的設(shè)置。
(2)為了讓用戶獲取網(wǎng)絡(luò)統(tǒng)計的數(shù)據(jù),驅(qū)動一般有一個net_device_stats結(jié)構(gòu)體,并提供get_stats函數(shù)接收它。
(3)應(yīng)用程序使用標準的socket、bind、send等操作。
本文采用第一種方法進行雙向ping通測試。首先在開發(fā)板終端上輸入命令ifconfig eth0 10.10.150.180,設(shè)置好開發(fā)板IP地址,再將網(wǎng)口通過網(wǎng)線與PC相連,查得PC IP地址是10.10.150.174。在Windows命令行界面上輸入命令ping 10.10.150.180,得到如下結(jié)果:
Ping 10.10.150.180 with 32 bytes of data:
Reply from 10.10.150.180:bytes=32 time<1ms TTL=64
Reply from 10.10.150.180:bytes=32 time<1ms TTL=64
Reply from 10.10.150.180:bytes=32 time<1ms TTL=64
接著在開發(fā)板終端上輸入命令ping 10.10.150.174,得到如下結(jié)果:
Ping 10.10.150.174(10.10.150.174):56 data bytes
64 bytes from 10.10.150.174:icmp_seq=0 ttl=64 time=0.9ms
64 bytes from 10.10.150.174:icmp_seq=1 ttl=64 time=0.9ms
64 bytes from 10.10.150.174:icmp_seq=2 ttl=64 time=0.9ms
測試結(jié)果表明網(wǎng)絡(luò)驅(qū)動正常。
4 結(jié)論
本文基于S3C2440開發(fā)板,通過外接DM9000網(wǎng)卡,完成網(wǎng)卡驅(qū)動的移植,編譯內(nèi)核生成內(nèi)核鏡像,實現(xiàn)網(wǎng)絡(luò)設(shè)備驅(qū)動的匹配。最后通過ping命令測試網(wǎng)口是否能正常工作。本文的移植方法可為其他網(wǎng)絡(luò)驅(qū)動移植作為參考。
參考文獻
[1] 李方軍,金煒東.嵌入式Linux網(wǎng)絡(luò)驅(qū)動程序的研究與實現(xiàn)[J].現(xiàn)代電子技術(shù),2005(16):20-30.
[2] 宋寶華.Linux設(shè)備驅(qū)動開發(fā)詳解[M].北京:人民郵電出版社,2010.
[3] 賀金平.嵌入式Linux下DM9000網(wǎng)卡驅(qū)動的移植與實現(xiàn)[J].電腦知識與技術(shù),2009,22(5):82-86.
[4] 丁忠,林暢衛(wèi).功基于Linux的網(wǎng)絡(luò)設(shè)備驅(qū)動程序設(shè)計[J].微計算機應(yīng)用,2007(9):56-77.
[5] 潘攀.Linux在嵌入式系統(tǒng)上的移植[J].科技信息,2010(20):45-63.
[6] 吳士力.嵌入式Linux應(yīng)用開發(fā)全程解析與實戰(zhàn)[M].北京:機械工業(yè)出版社,2010